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