1cb93a386Sopenharmony_ci#! /usr/bin/env python 2cb93a386Sopenharmony_ci 3cb93a386Sopenharmony_ci# Copyright 2018 Google LLC. 4cb93a386Sopenharmony_ci# Use of this source code is governed by a BSD-style license that can be 5cb93a386Sopenharmony_ci# found in the LICENSE file. 6cb93a386Sopenharmony_ci 7cb93a386Sopenharmony_ci 8cb93a386Sopenharmony_cifrom __future__ import print_function 9cb93a386Sopenharmony_cifrom subprocess import call, check_output, CalledProcessError 10cb93a386Sopenharmony_ciimport os 11cb93a386Sopenharmony_ciimport re 12cb93a386Sopenharmony_ciimport sys 13cb93a386Sopenharmony_ciimport tempfile 14cb93a386Sopenharmony_ci 15cb93a386Sopenharmony_ci 16cb93a386Sopenharmony_ciHEADER = '''<!DOCTYPE html> 17cb93a386Sopenharmony_ci<html lang="en"> 18cb93a386Sopenharmony_ci<head> 19cb93a386Sopenharmony_ci<meta charset="utf-8"> 20cb93a386Sopenharmony_ci<title>SkQP Pre-built APKs</title> 21cb93a386Sopenharmony_ci<meta name="viewport" content="width=device-width, initial-scale=1.0"> 22cb93a386Sopenharmony_ci<style> 23cb93a386Sopenharmony_cibody { 24cb93a386Sopenharmony_cifont-family:sans-serif; 25cb93a386Sopenharmony_cimax-width:50em; 26cb93a386Sopenharmony_cimargin:8px auto; 27cb93a386Sopenharmony_cipadding:0 8px; 28cb93a386Sopenharmony_ci} 29cb93a386Sopenharmony_citable { max-width:100%; border-collapse: collapse; } 30cb93a386Sopenharmony_citd { padding:12px 8px; vertical-align:top; } 31cb93a386Sopenharmony_citr:nth-child(even) {background: #F2F2F2; color:#000;} 32cb93a386Sopenharmony_citr:nth-child(odd) {background: #FFFFFF; color:#000;} 33cb93a386Sopenharmony_ci</style> 34cb93a386Sopenharmony_ci</head> 35cb93a386Sopenharmony_ci<body> 36cb93a386Sopenharmony_ci<h1>SkQP Pre-built APKs</h1> 37cb93a386Sopenharmony_ci''' 38cb93a386Sopenharmony_ciFOOTER = '</body>\n</html>\n' 39cb93a386Sopenharmony_ci 40cb93a386Sopenharmony_ciBUCKET = 'skia-skqp' 41cb93a386Sopenharmony_ci 42cb93a386Sopenharmony_ciNAME_FMT = 'skqp-universal-%s.apk' 43cb93a386Sopenharmony_ci 44cb93a386Sopenharmony_ci 45cb93a386Sopenharmony_cidef get_existing_files(): 46cb93a386Sopenharmony_ci cmd = ['gsutil', 'ls', 'gs://' + BUCKET] 47cb93a386Sopenharmony_ci try: 48cb93a386Sopenharmony_ci output = check_output(cmd) 49cb93a386Sopenharmony_ci except (OSError, CalledProcessError): 50cb93a386Sopenharmony_ci sys.stderr.write('command: "%s" failed.\n' % ' '.join(cmd)) 51cb93a386Sopenharmony_ci sys.exit(1) 52cb93a386Sopenharmony_ci result = set() 53cb93a386Sopenharmony_ci regex = re.compile('gs://%s/%s' % (BUCKET, NAME_FMT % '([0-9a-f]+)')) 54cb93a386Sopenharmony_ci for line in output.split('\n'): 55cb93a386Sopenharmony_ci m = regex.match(line.strip()) 56cb93a386Sopenharmony_ci if m is not None: 57cb93a386Sopenharmony_ci result.add(m.group(1)) 58cb93a386Sopenharmony_ci return result 59cb93a386Sopenharmony_ci 60cb93a386Sopenharmony_ci 61cb93a386Sopenharmony_cidef find(v, extant): 62cb93a386Sopenharmony_ci l = min(16, len(v)) 63cb93a386Sopenharmony_ci while l > 8: 64cb93a386Sopenharmony_ci if v[:l] in extant: 65cb93a386Sopenharmony_ci return v[:l] 66cb93a386Sopenharmony_ci l -= 1 67cb93a386Sopenharmony_ci return None 68cb93a386Sopenharmony_ci 69cb93a386Sopenharmony_ci 70cb93a386Sopenharmony_cidef nowrap(s): 71cb93a386Sopenharmony_ci return (s.replace(' ', u'\u00A0'.encode('utf-8')) 72cb93a386Sopenharmony_ci .replace('-', u'\u2011'.encode('utf-8'))) 73cb93a386Sopenharmony_ci 74cb93a386Sopenharmony_ci 75cb93a386Sopenharmony_cidef rev_parse(arg): 76cb93a386Sopenharmony_ci if isinstance(arg, tuple): 77cb93a386Sopenharmony_ci remote_url, branch = arg 78cb93a386Sopenharmony_ci for remote in check_output(['git', 'remote']).strip().split('\n'): 79cb93a386Sopenharmony_ci remote = remote.strip() 80cb93a386Sopenharmony_ci url = check_output(['git', 'remote', 'get-url', remote]).strip() 81cb93a386Sopenharmony_ci if url == remote_url: 82cb93a386Sopenharmony_ci arg = remote + '/' + branch 83cb93a386Sopenharmony_ci break 84cb93a386Sopenharmony_ci return check_output(['git', 'rev-parse', arg]).strip() 85cb93a386Sopenharmony_ci 86cb93a386Sopenharmony_ci 87cb93a386Sopenharmony_cidef table(o, remote, branch, excludes): 88cb93a386Sopenharmony_ci env_copy = os.environ.copy() 89cb93a386Sopenharmony_ci env_copy['TZ'] = '' 90cb93a386Sopenharmony_ci extant = get_existing_files() 91cb93a386Sopenharmony_ci 92cb93a386Sopenharmony_ci commits = [rev_parse((remote, branch))] 93cb93a386Sopenharmony_ci for exclude in excludes: 94cb93a386Sopenharmony_ci commits.append('^' + rev_parse(exclude)) 95cb93a386Sopenharmony_ci 96cb93a386Sopenharmony_ci o.write('<h2>Remote: %s<br>Branch: %s</h2>\n' % (remote, branch)) 97cb93a386Sopenharmony_ci o.write('<table>\n<tr><th>APK</th><th>Date</th><th>Commit</th></tr>\n') 98cb93a386Sopenharmony_ci git_cmd = ['git', 'log', '--format=%H;%cd;%<(100,trunc)%s', 99cb93a386Sopenharmony_ci '--date=format-local:%Y-%m-%d %H:%M:%S %Z'] + commits 100cb93a386Sopenharmony_ci commits = check_output(git_cmd, env=env_copy) 101cb93a386Sopenharmony_ci for line in commits.split('\n'): 102cb93a386Sopenharmony_ci line = line.strip() 103cb93a386Sopenharmony_ci if not line: 104cb93a386Sopenharmony_ci continue 105cb93a386Sopenharmony_ci commit, date, subj = line.split(';', 2) 106cb93a386Sopenharmony_ci short = find(commit, extant) 107cb93a386Sopenharmony_ci if short is not None: 108cb93a386Sopenharmony_ci apk_name = NAME_FMT % short 109cb93a386Sopenharmony_ci url = 'https://storage.googleapis.com/%s/%s' % (BUCKET, apk_name) 110cb93a386Sopenharmony_ci else: 111cb93a386Sopenharmony_ci apk_name, url = '', '' 112cb93a386Sopenharmony_ci commit_url = '%s/+/%s' % (remote, commit) 113cb93a386Sopenharmony_ci o.write('<tr>\n<td><a href="%s">%s</a></td>\n' 114cb93a386Sopenharmony_ci '<td>%s</td>\n<td><a href="%s">%s</a></td>\n</tr>\n' % 115cb93a386Sopenharmony_ci (url, nowrap(apk_name), nowrap(date), commit_url, subj)) 116cb93a386Sopenharmony_ci o.write('</table>\n') 117cb93a386Sopenharmony_ci 118cb93a386Sopenharmony_ci 119cb93a386Sopenharmony_cidef main(): 120cb93a386Sopenharmony_ci origin = 'https://skia.googlesource.com/skia' 121cb93a386Sopenharmony_ci aosp_skqp = 'https://android.googlesource.com/platform/external/skqp' 122cb93a386Sopenharmony_ci 123cb93a386Sopenharmony_ci assert '/' in [os.sep, os.altsep] and '..' == os.pardir 124cb93a386Sopenharmony_ci os.chdir(os.path.join(os.path.dirname(__file__), '../..')) 125cb93a386Sopenharmony_ci d = tempfile.mkdtemp() 126cb93a386Sopenharmony_ci path = os.path.join(d, 'apklist.html') 127cb93a386Sopenharmony_ci with open(path, 'w') as o: 128cb93a386Sopenharmony_ci o.write(HEADER) 129cb93a386Sopenharmony_ci table(o, origin, 'skqp/dev', [(origin, 'main'), '3e34285f2a0']) 130cb93a386Sopenharmony_ci table(o, origin, 'skqp/release', [(origin, 'main'), '09ab171c5c0']) 131cb93a386Sopenharmony_ci table(o, aosp_skqp, 'pie-cts-dev', ['f084c17322']) 132cb93a386Sopenharmony_ci o.write(FOOTER) 133cb93a386Sopenharmony_ci print(path) 134cb93a386Sopenharmony_ci call([sys.executable, 'bin/sysopen', path]) 135cb93a386Sopenharmony_ci gscmd = 'gsutil -h "Content-Type:text/html" cp "%s" gs://skia-skqp/apklist' 136cb93a386Sopenharmony_ci print(gscmd % path) 137cb93a386Sopenharmony_ci 138cb93a386Sopenharmony_ci 139cb93a386Sopenharmony_ciif __name__ == '__main__': 140cb93a386Sopenharmony_ci main() 141cb93a386Sopenharmony_ci 142