
* npm_binary (download tarball packaged npm apps) * bower_archive (download a zip file, to be put in WORKSPACE) * bower_component (defining a bower library, with dependency ) * bower_component_bundle (zipping up libraries together) * js_component (insert plain js file into bower component bundle) * bower2bazel.py: run bower to find dependencies, generate a .bzl to define archives and define components Tested: python tools/js/bower2bazel.py -w lib/js/bower_archives.bzl -b \ lib/js/bower_components.bzl bazel build polygerrit-ui:components unzip -v bazel-bin/polygerrit-ui/components.zip > /tmp/baz buck build polygerrit-ui:polygerrit_components unzip -v buck-out/gen/polygerrit-ui/polygerrit_components/polygerrit_components.bower_components.zip > /tmp/buck diff /tmp/buck /tmp/baz The diff corresponds to newer file versions pinned through bower2bazel. Change-Id: I4f33914d4853bcf8afe78b4719d0e0e83b139031
129 lines
3.9 KiB
Python
Executable File
129 lines
3.9 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.
|
|
|
|
from __future__ import print_function
|
|
|
|
import hashlib
|
|
import json
|
|
import optparse
|
|
import os
|
|
import shutil
|
|
import subprocess
|
|
import sys
|
|
|
|
import bowerutil
|
|
|
|
CACHE_DIR = os.path.expanduser(os.path.join(
|
|
'~', '.gerritcodereview', 'buck-cache', 'downloaded-artifacts'))
|
|
|
|
|
|
def bower_cmd(bower, *args):
|
|
cmd = bower.split(' ')
|
|
cmd.extend(args)
|
|
return cmd
|
|
|
|
|
|
def bower_info(bower, name, package, version):
|
|
cmd = bower_cmd(bower, '-l=error', '-j',
|
|
'info', '%s#%s' % (package, version))
|
|
try:
|
|
p = subprocess.Popen(cmd , stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
|
except:
|
|
sys.stderr.write("error executing: %s\n" % ' '.join(cmd))
|
|
raise
|
|
out, err = p.communicate()
|
|
if p.returncode:
|
|
sys.stderr.write(err)
|
|
raise OSError('Command failed: %s' % ' '.join(cmd))
|
|
|
|
try:
|
|
info = json.loads(out)
|
|
except ValueError:
|
|
raise ValueError('invalid JSON from %s:\n%s' % (" ".join(cmd), out))
|
|
info_name = info.get('name')
|
|
if info_name != name:
|
|
raise ValueError('expected package name %s, got: %s' % (name, info_name))
|
|
return info
|
|
|
|
|
|
def ignore_deps(info):
|
|
# Tell bower to ignore dependencies so we just download this component. This
|
|
# is just an optimization, since we only pick out the component we need, but
|
|
# it's important when downloading sizable dependency trees.
|
|
#
|
|
# As of 1.6.5 I don't think ignoredDependencies can be specified on the
|
|
# command line with --config, so we have to create .bowerrc.
|
|
deps = info.get('dependencies')
|
|
if deps:
|
|
with open(os.path.join('.bowerrc'), 'w') as f:
|
|
json.dump({'ignoredDependencies': deps.keys()}, f)
|
|
|
|
|
|
def cache_entry(name, package, version, sha1):
|
|
if not sha1:
|
|
sha1 = hashlib.sha1('%s#%s' % (package, version)).hexdigest()
|
|
return os.path.join(CACHE_DIR, '%s-%s.zip-%s' % (name, version, sha1))
|
|
|
|
|
|
def main(args):
|
|
opts = optparse.OptionParser()
|
|
opts.add_option('-n', help='short name of component')
|
|
opts.add_option('-b', help='bower command')
|
|
opts.add_option('-p', help='full package name of component')
|
|
opts.add_option('-v', help='version number')
|
|
opts.add_option('-s', help='expected content sha1')
|
|
opts.add_option('-o', help='output file location')
|
|
opts, args_ = opts.parse_args(args)
|
|
|
|
assert opts.p
|
|
assert opts.v
|
|
assert opts.n
|
|
|
|
cwd = os.getcwd()
|
|
outzip = os.path.join(cwd, opts.o)
|
|
cached = cache_entry(opts.n, opts.p, opts.v, opts.s)
|
|
|
|
if not os.path.exists(cached):
|
|
info = bower_info(opts.b, opts.n, opts.p, opts.v)
|
|
ignore_deps(info)
|
|
subprocess.check_call(
|
|
bower_cmd(opts.b, '--quiet', 'install', '%s#%s' % (opts.p, opts.v)))
|
|
bc = os.path.join(cwd, 'bower_components')
|
|
subprocess.check_call(
|
|
['zip', '-q', '--exclude', '.bower.json', '-r', cached, opts.n],
|
|
cwd=bc)
|
|
|
|
if opts.s:
|
|
path = os.path.join(bc, opts.n)
|
|
sha1 = bowerutil.hash_bower_component(hashlib.sha1(), path).hexdigest()
|
|
if opts.s != sha1:
|
|
print((
|
|
'%s#%s:\n'
|
|
'expected %s\n'
|
|
'received %s\n') % (opts.p, opts.v, opts.s, sha1), file=sys.stderr)
|
|
try:
|
|
os.remove(cached)
|
|
except OSError as err:
|
|
if path.exists(cached):
|
|
print('error removing %s: %s' % (cached, err), file=sys.stderr)
|
|
return 1
|
|
|
|
shutil.copyfile(cached, outzip)
|
|
return 0
|
|
|
|
|
|
if __name__ == '__main__':
|
|
sys.exit(main(sys.argv[1:]))
|