Remove bower and html plugin support
Gerrit hasn't support html plugins since 3.4 [1] and core removed bower
in 3.5 [2].
[1] 302255: Stop producing html version of plugins | https://gerrit-review.googlesource.com/c/gerrit/+/302255
[2] 304428: Bazel: Remove bower | https://gerrit-review.googlesource.com/c/gerrit/+/304428
Change-Id: Ib05956286ae719670a92da5255befe5ddb0a399b
diff --git a/gerrit_polymer.bzl b/gerrit_polymer.bzl
index bb448de..a7560d6 100644
--- a/gerrit_polymer.bzl
+++ b/gerrit_polymer.bzl
@@ -1,23 +1,7 @@
-load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive", "http_file")
+load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
def gerrit_polymer():
http_archive(
- name = "io_bazel_rules_closure",
- sha256 = "03c3b16f205085817fd89cfdcb2220a0138647ee7992be9cef291b069dd90301",
- strip_prefix = "rules_closure-196a45f0ede2faec11dcc6c60fbc5e7471f4bd58",
- urls = ["https://github.com/bazelbuild/rules_closure/archive/196a45f0ede2faec11dcc6c60fbc5e7471f4bd58.tar.gz"],
- )
-
- # File is specific to Polymer and copied from the Closure Github -- should be
- # synced any time there are major changes to Polymer.
- # https://github.com/google/closure-compiler/blob/master/contrib/externs/polymer-1.0.js
- http_file(
- name = "polymer_closure",
- sha256 = "5a589bdba674e1fec7188e9251c8624ebf2d4d969beb6635f9148f420d1e08b1",
- urls = ["https://raw.githubusercontent.com/google/closure-compiler/775609aad61e14aef289ebec4bfc09ad88877f9e/contrib/externs/polymer-1.0.js"],
- )
-
- http_archive(
name = "build_bazel_rules_nodejs",
sha256 = "c077680a307eb88f3e62b0b662c2e9c6315319385bc8c637a861ffdbed8ca247",
urls = ["https://github.com/bazelbuild/rules_nodejs/releases/download/5.1.0/rules_nodejs-5.1.0.tar.gz"],
diff --git a/lib/js/BUILD b/lib/js/BUILD
deleted file mode 100644
index 00301d3..0000000
--- a/lib/js/BUILD
+++ /dev/null
@@ -1 +0,0 @@
-# Empty marker file, indicating this directory is a Bazel package.
diff --git a/lib/js/externs/BUILD b/lib/js/externs/BUILD
deleted file mode 100644
index fab3954..0000000
--- a/lib/js/externs/BUILD
+++ /dev/null
@@ -1,25 +0,0 @@
-# Copyright (C) 2018 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.
-
-package(
- default_visibility = ["//visibility:public"],
-)
-
-load("@io_bazel_rules_closure//closure:defs.bzl", "closure_js_library")
-
-closure_js_library(
- name = "plugin",
- srcs = ["plugin.js"],
- no_closure_library = True,
-)
diff --git a/lib/js/externs/plugin.js b/lib/js/externs/plugin.js
deleted file mode 100644
index c88c724..0000000
--- a/lib/js/externs/plugin.js
+++ /dev/null
@@ -1,30 +0,0 @@
-/**
- * @license
- * Copyright (C) 2018 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.
- */
-
-/**
- * @fileoverview Closure compiler externs for the Gerrit UI plugins.
- * @externs
- */
-
-/* eslint-disable no-var */
-
-var Gerrit = {};
-
-/**
- * @param {!Function} callback
- */
-Gerrit.install = function(callback) {};
diff --git a/lib/js/npm.bzl b/lib/js/npm.bzl
deleted file mode 100644
index 92f44bd..0000000
--- a/lib/js/npm.bzl
+++ /dev/null
@@ -1,11 +0,0 @@
-NPM_VERSIONS = {
- "bower": "1.8.2",
- "crisper": "2.0.2",
- "polymer-bundler": "4.0.2",
-}
-
-NPM_SHA1S = {
- "bower": "adf53529c8d4af02ef24fb8d5341c1419d33e2f7",
- "crisper": "7183c58cea33632fb036c91cefd1b43e390d22a2",
- "polymer-bundler": "6b296b6099ab5a0e93ca914cbe93e753f2395910",
-}
diff --git a/lib/polymer_externs/BUILD b/lib/polymer_externs/BUILD
deleted file mode 100644
index 9a45508..0000000
--- a/lib/polymer_externs/BUILD
+++ /dev/null
@@ -1,32 +0,0 @@
-# Copyright (C) 2017 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.
-
-package(
- default_visibility = ["//visibility:public"],
-)
-
-load("@io_bazel_rules_closure//closure:defs.bzl", "closure_js_library")
-
-genrule(
- name = "polymer_closure_renamed",
- srcs = ["@polymer_closure//file"],
- outs = ["polymer_closure_renamed.js"],
- cmd = "cp $< $@",
-)
-
-closure_js_library(
- name = "polymer_closure",
- srcs = [":polymer_closure_renamed"],
- no_closure_library = True,
-)
diff --git a/tools/js.bzl b/tools/js.bzl
index 1b63a04..650be13 100644
--- a/tools/js.bzl
+++ b/tools/js.bzl
@@ -1,529 +1,7 @@
-load("@io_bazel_rules_closure//closure:defs.bzl", "closure_js_binary", "closure_js_library")
-load("//lib/js:npm.bzl", "NPM_SHA1S", "NPM_VERSIONS")
-
load("@npm//@bazel/rollup:index.bzl", "rollup_bundle")
load("@npm//@bazel/terser:index.bzl", "terser_minified")
load("@com_googlesource_gerrit_bazlets//tools:genrule2.bzl", "genrule2")
-NPMJS = "NPMJS"
-
-GERRIT = "GERRIT:"
-
-def _npm_tarball(name):
- return "%s@%s.npm_binary.tgz" % (name, NPM_VERSIONS[name])
-
-def _npm_binary_impl(ctx):
- """rule to download a NPM archive."""
- name = ctx.name
- version = NPM_VERSIONS[name]
- sha1 = NPM_SHA1S[name]
-
- dir = "%s-%s" % (name, version)
- filename = "%s.tgz" % dir
- base = "%s@%s.npm_binary.tgz" % (name, version)
- dest = ctx.path(base)
- repository = ctx.attr.repository
- if repository == GERRIT:
- url = "https://gerrit-maven.storage.googleapis.com/npm-packages/%s" % filename
- elif repository == NPMJS:
- url = "https://registry.npmjs.org/%s/-/%s" % (name, filename)
- else:
- fail("repository %s not in {%s,%s}" % (repository, GERRIT, NPMJS))
-
- python = ctx.which("python3")
- script = ctx.path(ctx.attr._download_script)
-
- args = [python, script, "-o", dest, "-u", url, "-v", sha1]
- out = ctx.execute(args)
- if out.return_code:
- fail("failed %s: %s" % (args, out.stderr))
- ctx.file("BUILD", "package(default_visibility=['//visibility:public'])\nfilegroup(name='tarball', srcs=['%s'])" % base, False)
-
-npm_binary = repository_rule(
- attrs = {
- "repository": attr.string(default = NPMJS),
- # Label resolves within repo of the .bzl file.
- "_download_script": attr.label(default = Label("//tools:download_file.py")),
- },
- local = True,
- implementation = _npm_binary_impl,
-)
-
-ComponentInfo = provider()
-
-# for use in repo rules.
-def _run_npm_binary_str(ctx, tarball, args):
- python_bin = ctx.which("python3")
- return " ".join([
- python_bin,
- ctx.path(ctx.attr._run_npm),
- ctx.path(tarball),
- ] + args)
-
-def _bower_archive(ctx):
- """Download a bower package."""
- download_name = "%s__download_bower.zip" % ctx.name
- renamed_name = "%s__renamed.zip" % ctx.name
- version_name = "%s__version.json" % ctx.name
-
- cmd = [
- ctx.which("python3"),
- ctx.path(ctx.attr._download_bower),
- "-b",
- "%s" % _run_npm_binary_str(ctx, ctx.attr._bower_archive, []),
- "-n",
- ctx.name,
- "-p",
- ctx.attr.package,
- "-v",
- ctx.attr.version,
- "-s",
- ctx.attr.sha1,
- "-o",
- download_name,
- ]
-
- out = ctx.execute(cmd)
- if out.return_code:
- fail("failed %s: %s" % (cmd, out.stderr))
-
- _bash(ctx, " && ".join([
- "TMP=$(mktemp -d || mktemp -d -t bazel-tmp)",
- "TZ=UTC",
- "export UTC",
- "cd $TMP",
- "mkdir bower_components",
- "cd bower_components",
- "unzip %s" % ctx.path(download_name),
- "cd ..",
- "find . -exec touch -t 198001010000 '{}' ';'",
- "zip -Xr %s bower_components" % renamed_name,
- "cd ..",
- "rm -rf ${TMP}",
- ]))
-
- dep_version = ctx.attr.semver if ctx.attr.semver else ctx.attr.version
- ctx.file(
- version_name,
- '"%s":"%s#%s"' % (ctx.name, ctx.attr.package, dep_version),
- )
- ctx.file(
- "BUILD",
- "\n".join([
- "package(default_visibility=['//visibility:public'])",
- "filegroup(name = 'zipfile', srcs = ['%s'], )" % download_name,
- "filegroup(name = 'version_json', srcs = ['%s'], visibility=['//visibility:public'])" % version_name,
- ]),
- False,
- )
-
-def _bash(ctx, cmd):
- cmd_list = ["bash", "-c", cmd]
- out = ctx.execute(cmd_list)
- if out.return_code:
- fail("failed %s: %s" % (cmd_list, out.stderr))
-
-bower_archive = repository_rule(
- _bower_archive,
- attrs = {
- "package": attr.string(mandatory = True),
- "semver": attr.string(),
- "sha1": attr.string(mandatory = True),
- "version": attr.string(mandatory = True),
- "_bower_archive": attr.label(default = Label("@bower//:%s" % _npm_tarball("bower"))),
- "_download_bower": attr.label(default = Label("//tools/js:download_bower.py")),
- "_run_npm": attr.label(default = Label("//tools/js:run_npm_binary.py")),
- },
-)
-
-def _bower_component_impl(ctx):
- transitive_zipfiles = depset(
- direct = [ctx.file.zipfile],
- transitive = [d[ComponentInfo].transitive_zipfiles for d in ctx.attr.deps],
- )
-
- transitive_licenses = depset(
- direct = [ctx.file.license],
- transitive = [d[ComponentInfo].transitive_licenses for d in ctx.attr.deps],
- )
-
- transitive_versions = depset(
- direct = ctx.files.version_json,
- transitive = [d[ComponentInfo].transitive_versions for d in ctx.attr.deps],
- )
-
- return [
- ComponentInfo(
- transitive_licenses = transitive_licenses,
- transitive_versions = transitive_versions,
- transitive_zipfiles = transitive_zipfiles,
- ),
- ]
-
-_common_attrs = {
- "deps": attr.label_list(providers = [ComponentInfo]),
-}
-
-def _js_component(ctx):
- dir = ctx.outputs.zip.path + ".dir"
- name = ctx.outputs.zip.basename
- if name.endswith(".zip"):
- name = name[:-4]
- dest = "%s/%s" % (dir, name)
- cmd = " && ".join([
- "TZ=UTC",
- "export TZ",
- "mkdir -p %s" % dest,
- "cp %s %s/" % (" ".join([s.path for s in ctx.files.srcs]), dest),
- "cd %s" % dir,
- "find . -exec touch -t 198001010000 '{}' ';'",
- "zip -Xqr ../%s *" % ctx.outputs.zip.basename,
- ])
-
- ctx.actions.run_shell(
- inputs = ctx.files.srcs,
- outputs = [ctx.outputs.zip],
- command = cmd,
- mnemonic = "GenBowerZip",
- )
-
- licenses = []
- if ctx.file.license:
- licenses.append(ctx.file.license)
-
- return [
- ComponentInfo(
- transitive_licenses = depset(licenses),
- transitive_versions = depset(),
- transitive_zipfiles = list([ctx.outputs.zip]),
- ),
- ]
-
-js_component = rule(
- _js_component,
- attrs = dict(_common_attrs.items() + {
- "srcs": attr.label_list(allow_files = [".js"]),
- "license": attr.label(allow_single_file = True),
- }.items()),
- outputs = {
- "zip": "%{name}.zip",
- },
-)
-
-_bower_component = rule(
- _bower_component_impl,
- attrs = dict(_common_attrs.items() + {
- "license": attr.label(allow_single_file = True),
-
- # If set, define by hand, and don't regenerate this entry in bower2bazel.
- "seed": attr.bool(default = False),
- "version_json": attr.label(allow_files = [".json"]),
- "zipfile": attr.label(allow_single_file = [".zip"]),
- }.items()),
-)
-
-# TODO(hanwen): make license mandatory.
-def bower_component(name, license = None, **kwargs):
- prefix = "//lib:LICENSE-"
- if license and not license.startswith(prefix):
- license = prefix + license
- _bower_component(
- name = name,
- license = license,
- zipfile = "@%s//:zipfile" % name,
- version_json = "@%s//:version_json" % name,
- **kwargs
- )
-
-def _bower_component_bundle_impl(ctx):
- """A bunch of bower components zipped up."""
- zips = depset()
- for d in ctx.attr.deps:
- files = d[ComponentInfo].transitive_zipfiles
-
- # TODO(davido): Make sure the field always contains a depset
- if type(files) == "list":
- files = depset(files)
- zips = depset(transitive = [zips, files])
-
- versions = depset(transitive = [d[ComponentInfo].transitive_versions for d in ctx.attr.deps])
-
- licenses = depset(transitive = [d[ComponentInfo].transitive_versions for d in ctx.attr.deps])
-
- out_zip = ctx.outputs.zip
- out_versions = ctx.outputs.version_json
-
- ctx.actions.run_shell(
- inputs = zips.to_list(),
- outputs = [out_zip],
- command = " && ".join([
- "p=$PWD",
- "TZ=UTC",
- "export TZ",
- "rm -rf %s.dir" % out_zip.path,
- "mkdir -p %s.dir/bower_components" % out_zip.path,
- "cd %s.dir/bower_components" % out_zip.path,
- "for z in %s; do unzip -q $p/$z ; done" % " ".join(sorted([z.path for z in zips.to_list()])),
- "cd ..",
- "find . -exec touch -t 198001010000 '{}' ';'",
- "zip -Xqr $p/%s bower_components/*" % out_zip.path,
- ]),
- mnemonic = "BowerCombine",
- )
-
- ctx.actions.run_shell(
- inputs = versions.to_list(),
- outputs = [out_versions],
- mnemonic = "BowerVersions",
- command = "(echo '{' ; for j in %s ; do cat $j; echo ',' ; done ; echo \\\"\\\":\\\"\\\"; echo '}') > %s" % (" ".join([v.path for v in versions.to_list()]), out_versions.path),
- )
-
- return [
- ComponentInfo(
- transitive_licenses = licenses,
- transitive_versions = versions,
- transitive_zipfiles = zips,
- ),
- ]
-
-bower_component_bundle = rule(
- _bower_component_bundle_impl,
- attrs = _common_attrs,
- outputs = {
- "version_json": "%{name}-versions.json",
- "zip": "%{name}.zip",
- },
-)
-
-def _bundle_impl(ctx):
- """Groups a set of .html and .js together in a zip file.
-
- Outputs:
- NAME-versions.json:
- a JSON file containing a PKG-NAME => PKG-NAME#VERSION mapping for the
- transitive dependencies.
- NAME.zip:
- a zip file containing the transitive dependencies for this bundle.
- """
-
- # intermediate artifact if split is wanted.
- if ctx.attr.split:
- bundled = ctx.actions.declare_file(ctx.outputs.html.path + ".bundled.html")
- else:
- bundled = ctx.outputs.html
- destdir = ctx.outputs.html.path + ".dir"
- zips = [z for d in ctx.attr.deps for z in d[ComponentInfo].transitive_zipfiles.to_list()]
-
- hermetic_npm_binary = " ".join([
- "python3",
- "$p/" + ctx.file._run_npm.path,
- "$p/" + ctx.file._bundler_archive.path,
- "--inline-scripts",
- "--inline-css",
- "--strip-comments",
- "--out-file",
- "$p/" + bundled.path,
- ctx.file.app.path,
- ])
-
- pkg_dir = ctx.attr.pkg.lstrip("/")
- cmd = " && ".join([
- # unpack dependencies.
- "export PATH",
- "p=$PWD",
- "rm -rf %s" % destdir,
- "mkdir -p %s/%s/bower_components" % (destdir, pkg_dir),
- "for z in %s; do unzip -qd %s/%s/bower_components/ $z; done" % (
- " ".join([z.path for z in zips]),
- destdir,
- pkg_dir,
- ),
- "tar -cf - %s | tar -C %s -xf -" % (" ".join([s.path for s in ctx.files.srcs]), destdir),
- "cd %s" % destdir,
- hermetic_npm_binary,
- ])
-
- # Node/NPM is not (yet) hermeticized, so we have to get the binary
- # from the environment, and it may be under $HOME, so we can't run
- # in the sandbox.
- node_tweaks = dict(
- execution_requirements = {"local": "1"},
- use_default_shell_env = True,
- )
- ctx.actions.run_shell(
- mnemonic = "Bundle",
- inputs = [
- ctx.file._run_npm,
- ctx.file.app,
- ctx.file._bundler_archive,
- ] + list(zips) + ctx.files.srcs,
- outputs = [bundled],
- command = cmd,
- **node_tweaks
- )
-
- if ctx.attr.split:
- hermetic_npm_command = "export PATH && " + " ".join([
- "python3",
- ctx.file._run_npm.path,
- ctx.file._crisper_archive.path,
- "--always-write-script",
- "--source",
- bundled.path,
- "--html",
- ctx.outputs.html.path,
- "--js",
- ctx.outputs.js.path,
- ])
-
- ctx.actions.run_shell(
- mnemonic = "Crisper",
- inputs = [
- ctx.file._run_npm,
- ctx.file.app,
- ctx.file._crisper_archive,
- bundled,
- ],
- outputs = [ctx.outputs.js, ctx.outputs.html],
- command = hermetic_npm_command,
- **node_tweaks
- )
-
-def _bundle_output_func(name, split):
- _ignore = [name] # unused.
- out = {"html": "%{name}.html"}
- if split:
- out["js"] = "%{name}.js"
- return out
-
-_bundle_rule = rule(
- _bundle_impl,
- attrs = {
- "srcs": attr.label_list(allow_files = [
- ".js",
- ".html",
- ".txt",
- ".css",
- ".ico",
- ]),
- "app": attr.label(
- mandatory = True,
- allow_single_file = True,
- ),
- "pkg": attr.string(mandatory = True),
- "split": attr.bool(default = True),
- "deps": attr.label_list(providers = [ComponentInfo]),
- "_bundler_archive": attr.label(
- default = Label("@polymer-bundler//:%s" % _npm_tarball("polymer-bundler")),
- allow_single_file = True,
- ),
- "_crisper_archive": attr.label(
- default = Label("@crisper//:%s" % _npm_tarball("crisper")),
- allow_single_file = True,
- ),
- "_run_npm": attr.label(
- default = Label("//tools/js:run_npm_binary.py"),
- allow_single_file = True,
- ),
- },
- outputs = _bundle_output_func,
-)
-
-def bundle_assets(*args, **kwargs):
- """Combine html, js, css files and optionally split into js and html bundles."""
- _bundle_rule(pkg = native.package_name(), *args, **kwargs)
-
-def polygerrit_plugin(name, app, srcs = [], assets = None, **kwargs):
- """Bundles plugin dependencies for deployment.
-
- This rule bundles all Polymer elements and JS dependencies into .html and .js files.
- Run-time dependencies (e.g. JS libraries loaded after plugin starts) should be provided using "assets" property.
- Output of this rule is a FileSet with "${name}_fs", with deploy artifacts in "plugins/${name}/static".
-
- Args:
- name: String, plugin name.
- app: String, the main or root source file.
- assets: Fileset, additional files to be used by plugin in runtime, exported to "plugins/${name}/static".
- srcs: Source files required for combining.
- """
-
- # Combines all .js and .html files into foo_combined.js and foo_combined.html
- _bundle_rule(
- name = name + "_combined",
- app = app,
- srcs = srcs if app in srcs else srcs + [app],
- pkg = native.package_name(),
- **kwargs
- )
-
- closure_js_binary(
- name = name + "_bin",
- compilation_level = "WHITESPACE_ONLY",
- defs = [
- "--polymer_version=1",
- "--language_out=ECMASCRIPT6",
- "--rewrite_polyfills=false",
- ],
- deps = [
- name + "_closure_lib",
- ],
- )
-
- closure_js_library(
- name = name + "_closure_lib",
- srcs = [name + "_combined.js"],
- convention = "GOOGLE",
- no_closure_library = True,
- deps = [
- "@com_googlesource_gerrit_bazlets//lib/polymer_externs:polymer_closure",
- "@com_googlesource_gerrit_bazlets//lib/js/externs:plugin",
- ],
- )
-
- native.genrule(
- name = name + "_rename_html",
- srcs = [name + "_combined.html"],
- outs = [name + ".html"],
- cmd = "sed 's/<script src=\"" + name + "_combined.js\"/<script src=\"" + name + ".js\"/g' $(SRCS) > $(OUTS)",
- output_to_bindir = True,
- )
-
- native.genrule(
- name = name + "_rename_js",
- srcs = [name + "_bin.js"],
- outs = [name + ".js"],
- cmd = "cp $< $@",
- output_to_bindir = True,
- )
-
- static_files = [
- name + ".js",
- name + ".html",
- ]
-
- if assets:
- nested, direct = [], []
- for x in assets:
- target = nested if "/" in x else direct
- target.append(x)
-
- static_files += direct
-
- if nested:
- native.genrule(
- name = name + "_copy_assets",
- srcs = assets,
- outs = [f.split("/")[-1] for f in nested],
- cmd = "cp $(SRCS) $(@D)",
- output_to_bindir = True,
- )
- static_files += [":" + name + "_copy_assets"]
-
- native.filegroup(
- name = name,
- srcs = static_files,
- )
-
def gerrit_js_bundle(name, srcs, entry_point):
"""Produces a Gerrit JavaScript bundle archive.
diff --git a/tools/js/BUILD b/tools/js/BUILD
index 1faf6b3..d696496 100644
--- a/tools/js/BUILD
+++ b/tools/js/BUILD
@@ -1,2 +1 @@
-exports_files(["run_npm_binary.py"])
exports_files(["eslint-chdir.js"])
diff --git a/tools/js/run_npm_binary.py b/tools/js/run_npm_binary.py
deleted file mode 100644
index bdee5ab..0000000
--- a/tools/js/run_npm_binary.py
+++ /dev/null
@@ -1,102 +0,0 @@
-#!/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 atexit
-from distutils import spawn
-import hashlib
-import os
-import shutil
-import subprocess
-import sys
-import tarfile
-import tempfile
-
-
-def extract(path, outdir, bin):
- if os.path.exists(os.path.join(outdir, bin)):
- return # Another process finished extracting, ignore.
-
- # Use a temp directory adjacent to outdir so shutil.move can use the same
- # device atomically.
- tmpdir = tempfile.mkdtemp(dir=os.path.dirname(outdir))
-
- def cleanup():
- try:
- shutil.rmtree(tmpdir)
- except OSError:
- pass # Too late now
- atexit.register(cleanup)
-
- def extract_one(mem):
- dest = os.path.join(outdir, mem.name)
- tar.extract(mem, path=tmpdir)
- try:
- os.makedirs(os.path.dirname(dest))
- except OSError:
- pass # Either exists, or will fail on the next line.
- shutil.move(os.path.join(tmpdir, mem.name), dest)
-
- with tarfile.open(path, 'r:gz') as tar:
- for mem in tar.getmembers():
- if mem.name != bin:
- extract_one(mem)
- # Extract bin last so other processes only short circuit when
- # extraction is finished.
- if bin in tar.getnames():
- extract_one(tar.getmember(bin))
-
-
-def main(args):
- path = args[0]
- suffix = '.npm_binary.tgz'
- tgz = os.path.basename(path)
-
- parts = tgz[:-len(suffix)].split('@')
-
- if not tgz.endswith(suffix) or len(parts) != 2:
- print('usage: %s <path/to/npm_binary>' % sys.argv[0], file=sys.stderr)
- return 1
-
- name, _ = parts
-
- # Avoid importing from gerrit because we don't want to depend on the right
- # working directory
- sha1 = hashlib.sha1(open(path, 'rb').read()).hexdigest()
- outdir = '%s-%s' % (path[:-len(suffix)], sha1)
- rel_bin = os.path.join('package', 'bin', name)
- rel_lib_bin = os.path.join('package', 'lib', 'bin', name + '.js')
- bin = os.path.join(outdir, rel_bin)
- libbin = os.path.join(outdir, rel_lib_bin)
- if not os.path.isfile(bin):
- extract(path, outdir, rel_bin)
-
- nodejs = spawn.find_executable('nodejs')
- if nodejs:
- # Debian installs Node.js as 'nodejs', due to a conflict with another
- # package.
- if not os.path.isfile(bin) and os.path.isfile(libbin):
- subprocess.check_call([nodejs, libbin] + args[1:])
- else:
- subprocess.check_call([nodejs, bin] + args[1:])
- elif not os.path.isfile(bin) and os.path.isfile(libbin):
- subprocess.check_call([libbin] + args[1:])
- else:
- subprocess.check_call([bin] + args[1:])
-
-
-if __name__ == '__main__':
- sys.exit(main(sys.argv[1:]))