playground: switch to using pgbundle tool
Change-Id: Iee60e95a34e2ad533d4bdd678abce9839c62c30e
diff --git a/tools/playground/builder/Dockerfile b/tools/playground/builder/Dockerfile
index eb7f08f..cb9bf3a 100644
--- a/tools/playground/builder/Dockerfile
+++ b/tools/playground/builder/Dockerfile
@@ -44,7 +44,7 @@
# your local version of the code. This is useful when developing and testing
# local changes to the builder tool.
# RUN rm $VEYRON_ROOT/veyron/go/bin/builder
-# ADD builder.go /usr/local/veyron/veyron/go/src/veyron/tools/playground/builder/builder.go
+# ADD main.go /usr/local/veyron/veyron/go/src/veyron/tools/playground/builder/main.go
# ADD identity.go /usr/local/veyron/veyron/go/src/veyron/tools/playground/builder/identity.go
# ADD services.go /usr/local/veyron/veyron/go/src/veyron/tools/playground/builder/services.go
# RUN veyron go install veyron/tools/playground/builder
diff --git a/tools/playground/builder/builder.go b/tools/playground/builder/main.go
similarity index 100%
rename from tools/playground/builder/builder.go
rename to tools/playground/builder/main.go
diff --git a/tools/playground/pgbundle/.gitignore b/tools/playground/pgbundle/.gitignore
new file mode 100644
index 0000000..93f1361
--- /dev/null
+++ b/tools/playground/pgbundle/.gitignore
@@ -0,0 +1,2 @@
+node_modules
+npm-debug.log
diff --git a/tools/playground/pgbundle/.jshintignore b/tools/playground/pgbundle/.jshintignore
new file mode 100644
index 0000000..3c3629e
--- /dev/null
+++ b/tools/playground/pgbundle/.jshintignore
@@ -0,0 +1 @@
+node_modules
diff --git a/tools/playground/pgbundle/.jshintrc b/tools/playground/pgbundle/.jshintrc
new file mode 100644
index 0000000..b264540
--- /dev/null
+++ b/tools/playground/pgbundle/.jshintrc
@@ -0,0 +1,27 @@
+{
+ "camelcase": true,
+ "eqeqeq": true,
+ "expr": true,
+ "forin": true,
+ "freeze": true,
+ "immed": true,
+ "indent": 2,
+ "latedef": "nofunc",
+ "maxlen": 80,
+ "newcap": true,
+ "noarg": true,
+ "nonbsp": true,
+ "nonew": true,
+ "quotmark": "single",
+ "sub": true,
+ "trailing": true,
+ "undef": true,
+ "unused": "vars",
+
+ "browser": true,
+ "devel": true,
+ "node": true,
+
+ "globals": {
+ }
+}
diff --git a/tools/playground/pgbundle/Makefile b/tools/playground/pgbundle/Makefile
new file mode 100644
index 0000000..43cd1c5
--- /dev/null
+++ b/tools/playground/pgbundle/Makefile
@@ -0,0 +1,11 @@
+export SHELL := /bin/bash -euo pipefail
+
+node_modules: package.json
+ npm prune
+ npm install
+ touch node_modules
+
+lint:
+ jshint .
+
+.PHONY: lint
diff --git a/tools/playground/pgbundle/bin/pgbundle b/tools/playground/pgbundle/bin/pgbundle
new file mode 100755
index 0000000..599c379
--- /dev/null
+++ b/tools/playground/pgbundle/bin/pgbundle
@@ -0,0 +1,2 @@
+#!/usr/bin/env node
+require('../index.js').run();
diff --git a/tools/playground/pgbundle/index.js b/tools/playground/pgbundle/index.js
new file mode 100644
index 0000000..a05099a
--- /dev/null
+++ b/tools/playground/pgbundle/index.js
@@ -0,0 +1,117 @@
+var _ = require('lodash');
+var fs = require('fs');
+var glob = require('glob');
+var path = require('path');
+
+// Filename to write the data to.
+var BUNDLE_NAME = 'bundle.json';
+
+module.exports = {run: run};
+
+// TODO(nlacasse): improve this.
+function usage() {
+ console.log('Usage: pgbundle [options] <path> [<path> <path> ...]');
+ console.log('Options: --verbose: Enable verbose output.');
+ process.exit(1);
+}
+
+// If the first line is "// +build OMIT", strip the line and return the
+// remaining lines.
+function stripBuildOmit(lines) {
+ if (lines[0] === '// +build OMIT') {
+ return _.rest(lines);
+ }
+ return lines;
+}
+
+// If the first line is an index comment, strip the line and return the index
+// and remaining lines.
+function getIndex(lines) {
+ var index = null;
+ var match = lines[0].match(/^\/\/\s*index=(\d+)/);
+ if (match && match[1]) {
+ index = match[1];
+ lines = _.rest(lines);
+ }
+ return {
+ index: index,
+ lines: lines
+ };
+}
+
+function shouldIgnore(fileName) {
+ // Ignore directories.
+ if (_.last(fileName) === '/') {
+ return true;
+ }
+ // Ignore bundle files.
+ if (fileName === BUNDLE_NAME) {
+ return true;
+ }
+ // Ignore generated .vdl.go files.
+ if ((/\.vdl\.go$/i).test(fileName)) {
+ return true;
+ }
+ return false;
+}
+
+// Main function.
+function run() {
+ // Get the paths from process.argv.
+ var argv = require('minimist')(process.argv.slice(2));
+ var dirs = argv._;
+
+ // Make sure there is at least one path.
+ if (!dirs || dirs.length === 0) {
+ return usage();
+ }
+
+ // Loop over each path.
+ _.each(dirs, function(dir) {
+ var subFiles = glob.sync('**', {
+ cwd: dir,
+ mark: true // Add a '/' char to directory matches.
+ });
+
+ if (subFiles.length === 0) {
+ return usage();
+ }
+
+ var out = {files: []};
+
+ // Loop over each subfile in the path.
+ _.each(subFiles, function(fileName) {
+ if (shouldIgnore(fileName)) {
+ return;
+ }
+
+ var fullFilePath = path.resolve(dir, fileName);
+ var text = fs.readFileSync(fullFilePath, {encoding: 'utf8'});
+
+ var lines = text.split('\n');
+ lines = stripBuildOmit(lines);
+ var indexAndLines = getIndex(lines);
+ var index = indexAndLines.index;
+ lines = indexAndLines.lines;
+
+ // TODO(sadovsky): Should we put the index in the bundle? Note that we
+ // already order files by index below. The playground client currently
+ // does not use the index.
+ out.files.push({
+ name: path.basename(fileName),
+ body: lines.join('\n'),
+ index: index
+ });
+ });
+
+ out.files = _.sortBy(out.files, 'index');
+
+ // Write the bundle.json.
+ var outFile = path.resolve(dir, BUNDLE_NAME);
+ fs.writeFileSync(outFile, JSON.stringify(out));
+
+ if (argv.verbose) {
+ console.log('Wrote ' + outFile);
+ }
+ });
+}
diff --git a/tools/playground/pgbundle/package.json b/tools/playground/pgbundle/package.json
new file mode 100644
index 0000000..71ef866
--- /dev/null
+++ b/tools/playground/pgbundle/package.json
@@ -0,0 +1,20 @@
+{
+ "name": "pgbundle",
+ "description": "Playground file bundler",
+ "version": "0.0.1",
+ "bin": "./bin/pgbundle",
+ "bugs": {
+ "url": "https://github.com/veyron/pgbundle/issues"
+ },
+ "dependencies": {
+ "glob": "^4.0.6",
+ "lodash": "^2.4.1",
+ "minimist": "^1.1.0"
+ },
+ "homepage": "https://github.com/veyron/pgbundle",
+ "private": true,
+ "repository": {
+ "type": "git",
+ "url": "https://github.com/veyron/pgbundle.git"
+ }
+}
diff --git a/tools/playground/test.sh b/tools/playground/test.sh
index 2d99198..04f5236 100755
--- a/tools/playground/test.sh
+++ b/tools/playground/test.sh
@@ -4,54 +4,55 @@
source "${VEYRON_ROOT}/scripts/lib/shell_test.sh"
+# Installs the veyron.js library and makes it accessible to javascript files in
+# the veyron playground test folder under the module name 'veyron'.
install_veyron_js() {
- # This installs the veyron.js library, and makes it accessable to javascript
- # files in the veyron playground test folder under the module name 'veyron'.
- #
- # TODO(nlacasse): Once veyron.js is installed in a public npm registry, this
- # should be replaced with just "npm install veyron".
+ # TODO(nlacasse): Once veyron.js is publicly available in npm, replace this
+ # with "npm install veyron".
pushd "${VEYRON_ROOT}/veyron.js"
"${VEYRON_ROOT}/environment/cout/node/bin/npm" link
popd
"${VEYRON_ROOT}/environment/cout/node/bin/npm" link veyron
}
+# Installs the pgbundle tool.
+install_pgbundle() {
+ pushd "${VEYRON_ROOT}/veyron/go/src/veyron.io/veyron/veyron/tools/playground/pgbundle"
+ "${VEYRON_ROOT}/environment/cout/node/bin/npm" link
+ popd
+ "${VEYRON_ROOT}/environment/cout/node/bin/npm" link pgbundle
+}
+
build() {
- veyron go build veyron.io/veyron/veyron/tools/identity || shell_test::fail "line ${LINENO}: failed to build 'identity'"
- veyron go build veyron.io/veyron/veyron/services/proxy/proxyd || shell_test::fail "line ${LINENO}: failed to build 'proxyd'"
- veyron go build veyron.io/veyron/veyron/services/mounttable/mounttabled || shell_test::fail "line ${LINENO}: failed to build 'mounttabled'"
+ # Note that "go build" puts built binaries in $(pwd), but only if they are
+ # built one at a time. So much for the principle of least surprise...
+ local -r V="veyron.io/veyron/veyron"
+ veyron go build $V/tools/identity || shell_test::fail "line ${LINENO}: failed to build 'identity'"
+ veyron go build $V/services/proxy/proxyd || shell_test::fail "line ${LINENO}: failed to build 'proxyd'"
+ veyron go build $V/services/mounttable/mounttabled || shell_test::fail "line ${LINENO}: failed to build 'mounttabled'"
+ veyron go build $V/tools/playground/builder || shell_test::fail "line ${LINENO}: failed to build 'builder'"
veyron go build veyron.io/veyron/veyron2/vdl/vdl || shell_test::fail "line ${LINENO}: failed to build 'vdl'"
- veyron go build veyron.io/veyron/veyron/tools/playground/builder || shell_test::fail "line ${LINENO}: failed to build 'builder'"
- veyron go build veyron.io/veyron/veyron/tools/playground/testdata/escaper || shell_test::fail "line ${LINENO}: failed to build 'escaper'"
veyron go build veyron.io/wspr/veyron/services/wsprd || shell_test::fail "line ${LINENO}: failed to build 'wsprd'"
}
test_with_files() {
- echo '{"Files":[' > request.json
- while [[ "$#" > 0 ]]; do
- echo '{"Name":"'"$(basename $1)"'","Body":' >>request.json
- grep -v OMIT "$1" | ./escaper >>request.json
- shift
- if [[ "$#" > 0 ]]; then
- echo '},' >>request.json
- else
- echo '}' >>request.json
- fi
- done
- echo ']}' >>request.json
+ local -r TESTDIR=$(shell::tmp_dir)
+ cp "$@" ${TESTDIR}
+ ./node_modules/.bin/pgbundle ${TESTDIR}
rm -f builder.out
- ./builder <request.json 2>&1 | tee builder.out
+ ./builder < "${TESTDIR}/bundle.json" 2>&1 | tee builder.out
}
main() {
cd $(shell::tmp_dir)
build
install_veyron_js
+ install_pgbundle
local -r DIR="${VEYRON_ROOT}/veyron/go/src/veyron.io/veyron/veyron/tools/playground/testdata"
- export GOPATH="$(pwd)":"$(veyron env GOPATH)"
- export VDLPATH="$(pwd)":"$(veyron env VDLPATH)"
+ export GOPATH="$(pwd):$(veyron env GOPATH)"
+ export VDLPATH="$(pwd):$(veyron env VDLPATH)"
export PATH="$(pwd):${PATH}"
# Test without identities
@@ -88,9 +89,7 @@
grep -q "ipc: not authorized" builder.out || shell_test::fail "line ${LINENO}: rpc with expired id succeeded"
test_with_files "${DIR}/pong/pong.js" "${DIR}/ping/ping.js" "${DIR}/ids/expired.id" || shell_test::fail "line ${LINENO}: failed to build with expired id (js -> js)"
- # TODO(nlacasse): The error message in this case is very bad. Clean up the
- # veyron.js errors and change this to something reasonable.
- grep -q "vError.InternalError" builder.out || shell_test::fail "line ${LINENO}: rpc with expired id succeeded"
+ grep -q "ipc: not authorized" builder.out || shell_test::fail "line ${LINENO}: rpc with expired id succeeded"
# Test with unauthorized identities
diff --git a/tools/playground/testdata/escaper/main.go b/tools/playground/testdata/escaper/main.go
deleted file mode 100644
index 9f867e1..0000000
--- a/tools/playground/testdata/escaper/main.go
+++ /dev/null
@@ -1,19 +0,0 @@
-package main
-
-import (
- "encoding/json"
- "io/ioutil"
- "os"
-)
-
-func main() {
- data, err := ioutil.ReadAll(os.Stdin)
- if err != nil {
- panic(err)
- }
- out, err := json.Marshal(string(data))
- if err != nil {
- panic(err)
- }
- os.Stdout.Write(out)
-}