Files
gerrit/tools/js/bower2bazel.py
Becky Siegel 8a70455ae8 Update bower2bazel to fetch correct packages
Previously, bower2bazel tried to fetch whatever was registered in
bower with the package name. If the package author was specified it was
ignored. There was an issue with installing a new package (paper-button)
in which bower tried to fetch the wrong dependency. (paper-ripple).

This change updates the package to use the original source, so that the
bower-archives file looks like:

bower_archive(
    name = "paper-ripple",
    package = "polymerelements/paper-ripple",
    version = "1.0.10",
    sha1 = "21199db50d02b842da54bd6f4f1d1b10b474e893")

Change-Id: I4d1f797a86bd80e8b9cf119e21ee7c2f5387b77e
2017-08-29 18:21:58 +00:00

227 lines
6.6 KiB
Python
Executable File

#!/usr/bin/env python
# Copyright (C) 2015 The Android Open Source Project
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Suggested call sequence:
python tools/js/bower2bazel.py -w lib/js/bower_archives.bzl -b lib/js/bower_components.bzl
"""
from __future__ import print_function
import collections
import json
import hashlib
import optparse
import os
import subprocess
import sys
import tempfile
import glob
import bowerutil
# list of licenses for packages that don't specify one in their bower.json file.
package_licenses = {
"es6-promise": "es6-promise",
"fetch": "fetch",
"iron-a11y-announcer": "polymer",
"iron-a11y-keys-behavior": "polymer",
"iron-autogrow-textarea": "polymer",
"iron-behaviors": "polymer",
"iron-dropdown": "polymer",
"iron-fit-behavior": "polymer",
"iron-flex-layout": "polymer",
"iron-form-element-behavior": "polymer",
"iron-input": "polymer",
"iron-meta": "polymer",
"iron-overlay-behavior": "polymer",
"iron-resizable-behavior": "polymer",
"iron-selector": "polymer",
"iron-validatable-behavior": "polymer",
"moment": "moment",
"neon-animation": "polymer",
"page": "page.js",
"polymer": "polymer",
"polymer-resin": "polymer",
"promise-polyfill": "promise-polyfill",
"web-animations-js": "Apache2.0",
"webcomponentsjs": "polymer",
}
def build_bower_json(version_targets, seeds):
"""Generate bower JSON file, return its path.
Args:
version_targets: bazel target names of the versions.json file.
seeds: an iterable of bower package names of the seed packages, ie.
the packages whose versions we control manually.
"""
bower_json = collections.OrderedDict()
bower_json['name'] = 'bower2bazel-output'
bower_json['version'] = '0.0.0'
bower_json['description'] = 'Auto-generated bower.json for dependency management'
bower_json['private'] = True
bower_json['dependencies'] = {}
seeds = set(seeds)
for v in version_targets:
path = os.path.join("bazel-out/*-fastbuild/bin", v.lstrip("/").replace(":", "/"))
fs = glob.glob(path)
assert len(fs) == 1, '%s: file not found or multiple files found: %s' % (path, fs)
with open(fs[0]) as f:
j = json.load(f)
if "" in j:
# drop dummy entries.
del j[""]
trimmed = {}
for k, v in j.items():
if k in seeds:
trimmed[k] = v
bower_json['dependencies'].update(trimmed)
tmpdir = tempfile.mkdtemp()
ret = os.path.join(tmpdir, 'bower.json')
with open(ret, 'w') as f:
json.dump(bower_json, f, indent=2)
return ret
def bower_command(args):
base = subprocess.check_output(["bazel", "info", "output_base"]).strip()
exp = os.path.join(base, "external", "bower", "*npm_binary.tgz")
fs = sorted(glob.glob(exp))
assert len(fs) == 1, "bower tarball not found or have multiple versions %s" % fs
return ["python", os.getcwd() + "/tools/js/run_npm_binary.py", sorted(fs)[0]] + args
def main(args):
opts = optparse.OptionParser()
opts.add_option('-w', help='.bzl output for WORKSPACE')
opts.add_option('-b', help='.bzl output for //lib:BUILD')
opts, args = opts.parse_args()
target_str = subprocess.check_output([
"bazel", "query", "kind(bower_component_bundle, //polygerrit-ui/...)"])
seed_str = subprocess.check_output([
"bazel", "query", "attr(seed, 1, kind(bower_component, deps(//polygerrit-ui/...)))"])
targets = [s for s in target_str.split('\n') if s]
seeds = [s for s in seed_str.split('\n') if s]
prefix = "//lib/js:"
non_seeds = [s for s in seeds if not s.startswith(prefix)]
assert not non_seeds, non_seeds
seeds = set([s[len(prefix):] for s in seeds])
version_targets = [t + "-versions.json" for t in targets]
subprocess.check_call(['bazel', 'build'] + version_targets)
bower_json_path = build_bower_json(version_targets, seeds)
dir = os.path.dirname(bower_json_path)
cmd = bower_command(["install"])
build_out = sys.stdout
if opts.b:
build_out = open(opts.b + ".tmp", 'w')
ws_out = sys.stdout
if opts.b:
ws_out = open(opts.w + ".tmp", 'w')
header = """# DO NOT EDIT
# generated with the following command:
#
# %s
#
""" % ' '.join(sys.argv)
ws_out.write(header)
build_out.write(header)
oldwd = os.getcwd()
os.chdir(dir)
subprocess.check_call(cmd)
interpret_bower_json(seeds, ws_out, build_out)
ws_out.close()
build_out.close()
os.chdir(oldwd)
os.rename(opts.w + ".tmp", opts.w)
os.rename(opts.b + ".tmp", opts.b)
def dump_workspace(data, seeds, out):
out.write('load("//tools/bzl:js.bzl", "bower_archive")\n\n')
out.write('def load_bower_archives():\n')
for d in data:
if d["name"] in seeds:
continue
out.write(""" bower_archive(
name = "%(name)s",
package = "%(normalized-name)s",
version = "%(version)s",
sha1 = "%(bazel-sha1)s")
""" % d)
def dump_build(data, seeds, out):
out.write('load("//tools/bzl:js.bzl", "bower_component")\n\n')
out.write('def define_bower_components():\n')
for d in data:
out.write(" bower_component(\n")
out.write(" name = \"%s\",\n" % d["name"])
out.write(" license = \"//lib:LICENSE-%s\",\n" % d["bazel-license"])
deps = sorted(d.get("dependencies", {}).keys())
if deps:
if len(deps) == 1:
out.write(" deps = [ \":%s\" ],\n" % deps[0])
else:
out.write(" deps = [\n")
for dep in deps:
out.write(" \":%s\",\n" % dep)
out.write(" ],\n")
if d["name"] in seeds:
out.write(" seed = True,\n")
out.write(" )\n")
# done
def interpret_bower_json(seeds, ws_out, build_out):
out = subprocess.check_output(["find", "bower_components/", "-name", ".bower.json"])
data = []
for f in sorted(out.split('\n')):
if not f:
continue
pkg = json.load(open(f))
pkg_name = pkg["name"]
pkg["bazel-sha1"] = bowerutil.hash_bower_component(
hashlib.sha1(), os.path.dirname(f)).hexdigest()
license = package_licenses.get(pkg_name, "DO_NOT_DISTRIBUTE")
pkg["bazel-license"] = license
pkg["normalized-name"] = pkg["_originalSource"]
data.append(pkg)
dump_workspace(data, seeds, ws_out)
dump_build(data, seeds, build_out)
if __name__ == '__main__':
main(sys.argv[1:])