diff --git a/configs/client-config_test.js b/configs/client-config_test.js new file mode 100755 index 00000000..180f521a --- /dev/null +++ b/configs/client-config_test.js @@ -0,0 +1,140 @@ +#!/usr/bin/env node +/*global describe it*/ +"use strict"; + +"use server"; + + +require("amd-loader"); +require("c9/inline-mocha")(module); + +var assert = require("assert"); +var fs = require("fs"); + +describe("client config consistency", function(){ + // this.timeout(60000); + + var fileCache = Object.create(null); + var clientOptions; + var root = __dirname + "/../"; + + it("should get clientOptions from server", function(next) { + fetchClientOptions(function(err, clientOptions) { + assert(!err && clientOptions); + next(); + }); + }); + + fs.readdirSync(root + "/configs").forEach(function(name) { + if (!/client-(workspace|ssh|default)/.test(name)) return; + + it("should not have missing plugins in config " + name, function(next) { + fetchClientOptions(function(err, clientOptions) { + if (err) return next(); + checkConfig(name, clientOptions, next); + }); + }); + }); + + function fetchClientOptions(callback) { + if (clientOptions) + return callback(null, JSON.parse(JSON.stringify(clientOptions))); + var server = require(root + "/server.js"); + server(["--_getConfig", "-l", "localhost", "--collab=true"], "", function(e, plugins) { + clientOptions = plugins.filter(function(p) { + return /standalone[\\\/]standalone/.test(p.packagePath); + })[0].options; + fetchClientOptions(callback); + }); + } + + function checkConfig(name, clientOptions, next) { + var hasError = false; + var configPath = root + "/configs/" + name; + var configPathReal = fs.realpathSync(configPath); + var clientPlugins = require(configPath)(clientOptions); + + clientPlugins = clientPlugins.map(function(p, i) { + if (typeof p == "string") + return {packagePath: p}; + return p; + }); + clientPlugins.forEach(function(p) { + if (p.packagePath) { + if (!fileCache[p.packagePath]) { + + var filePath; + try { + filePath = require.resolve(p.packagePath); + } + catch (e) { + try { + filePath = require.resolve(p.packagePath.replace(/^plugins\//, "")); + } catch (e) { + // TODO instead of quessing we need a simple way of getting pathmap + if (configPath != configPathReal) + filePath = require.resolve(configPathReal + "/../../node_modules/" + p.packagePath.replace(/^plugins\//, "")); + } + } + if (!filePath.match(/\.js$/)) + filePath += ".js"; + + fileCache[p.packagePath] = fs.readFileSync(filePath, "utf8"); + } + var source = fileCache[p.packagePath]; + p.provides = getDeps("provides", source); + p.consumes = getDeps("consumes", source); + } + }); + + var provides = {"auth.bootstrap": 1, "hub": 1}; + var paths = {}; + clientPlugins.forEach(function(p) { + if (paths[p.packagePath]) { + console.error(name, paths[p.packagePath].packagePath, p.packagePath); + hasError = true; + } + paths[p.packagePath] = p; + p.provides && p.provides.forEach(function(name) { + if (provides[name]) { + // console.warn(name, p.packagePath, provides[name]); + } + provides[name] = p.packagePath; + }); + }); + var unresolved = []; + clientPlugins.forEach(function(p) { + var missing = (p.consumes || []).filter(function(name) { + return !provides[name]; + }); + if (missing.length) { + unresolved.push({ + packagePath: p.packagePath, + missing: missing + }); + } + }); + + if (unresolved.length) { + // not throwing an error to check all configs + hasError = true; + } + + function getDeps(type, source) { + var re = new RegExp(type + /\s*=\s*(\[[^\[\]]*\])/.source); + var m = source.match(re); + if (!m) return []; + m = m[1].replace(/\/\/.*|\/\*[\s\S]*?\*\//g, "") + .replace(/,\s*\]/g, "]") + .replace(/'/g, "\""); + return JSON.parse(m); + } + assert(!unresolved.length, ( + "unresolved plugins in /configs/" + name + + JSON.stringify(unresolved, null, 4) + ).replace(/^/gm, "\t") + ); + next(); + } + +}); diff --git a/integrations/scripts/update.sh b/integrations/scripts/update.sh index fc042e5d..8ce2487d 100755 --- a/integrations/scripts/update.sh +++ b/integrations/scripts/update.sh @@ -2,13 +2,17 @@ set -e cd `dirname $0`/.. -# set -x NAME=$1 shift BRANCH=master URL= +FORCE= for i in "$@"; do case $i in + -d|--debug) + set -x + shift + ;; -b=*|--branch=*) BRANCH="${i#*=}" shift @@ -17,6 +21,10 @@ for i in "$@"; do URL="${i#*=}" shift ;; + -f|--force|--hard) + FORCE=1 + shift + ;; *) # unknown option ;; @@ -28,70 +36,106 @@ if [ "$NAME" == "" ]; then exit 0 fi -echo adding name=$NAME url=$URL branch=refs/remotes/origin/$BRANCH - -if [ "$URL" == "" ]; then - URL=git@github.com:c9/$NAME.git -fi - -if [ -d $NAME/.git ]; then +update_one() { + echo adding name=$NAME url=$URL branch=refs/remotes/origin/$BRANCH + + if [ "$URL" == "" ]; then + URL=git@github.com:c9/$NAME.git + fi + + mkdir -p $NAME pushd $NAME + + if ! [ -d .git ]; then + git init . + git remote add origin "$URL" + fi + OLD_URL=$(git config --get remote.origin.url) if [ "$OLD_URL" != "$URL" ]; then echo "folder $NAME exists and points to $OLD_URL" exit 1 fi + if ! $(git config --get-all remote.origin.fetch | grep -q pull); then + git config --add remote.origin.fetch "+refs/pull/*/head:refs/remotes/pull/*"; + fi git fetch origin git remote set-head origin -a popd + + pushd $NAME + HASH=$(git rev-parse --revs-only refs/remotes/origin/$BRANCH) + if [ "$FORCE" == "1" ]; then + echo "hard reset $NAME to $HASH" + git reset $HASH --hard + if $(grep -q dependencies "./package.json"); then + rm -rf node_modules npm-shrinkwrap.json + git reset --hard + npm i + npm shrinkwrap + fi + fi + popd + + [ -f ./config.json ] || echo "{}" > ./config.json + node -e ' + var name = "'$NAME'"; + var url = "'$URL'"; + var hash = "'$HASH'".trim(); + var fs = require("fs"); + + function updateJSON(path, fn) { + var text = fs.readFileSync(path, "utf8"); + var indent = text.match(/^\s*(?=")/m); + indent = indent && indent[0] || 4; + console.log(indent) + var r = JSON.parse(text); + r = fn(r) || r; + text = JSON.stringify(r, null, indent) + "\n"; + fs.writeFileSync(path, text, "utf8"); + } + + updateJSON("./config.json", function(config) { + var packages = config.packages || (config.packages = {}); + config.packages[name] = { + name: name, + hash: hash, + url: url, + }; + }); + updateJSON("../package.json", function(package) { + var deps = package.dependencies; + console.log(deps[name], hash); + deps[name] = deps[name].replace(/#[a-f\d]*$/i, "#" + hash); + console.log(deps[name], hash); + }); + updateJSON("../npm-shrinkwrap.json", function(package) { + var deps = package.dependencies; + deps[name].from = deps[name].from.replace(/#[a-f\d]*$/i, "#" + hash); + deps[name].resolved = deps[name].resolved.replace(/#[a-f\d]*$/i, "#" + hash); + console.log(__dirname) + if (fs.existsSync(name + "/npm-shrinkwrap.json")) { + var shrinkwrap = JSON.parse(fs.readFileSync(name + "/npm-shrinkwrap.json", "utf8")); + deps[name].dependencies = shrinkwrap.dependencies; + } + }); + ' + + rm -rf "../node_modules/$NAME" + ln -s `pwd`/$NAME `pwd`/../node_modules/$NAME +} + + +if [ "$NAME" == "all" ]; then + for i in $(ls .); do + if [ -d "./$i/.git" ] || [ -f "./$i/package.json" ]; then + NAME=$i + URL= + update_one; + fi; + done else - mkdir -p $NAME - git clone $URL $NAME + update_one fi -pushd $NAME -HASH=$(git rev-parse --revs-only refs/remotes/origin/$BRANCH) -popd - -[ -f ./config.json ] || echo "{}" > ./config.json -node -e ' - var name = "'$NAME'"; - var url = "'$URL'"; - var hash = "'$HASH'".trim(); - var fs = require("fs"); - - function updateJSON(path, fn) { - var text = fs.readFileSync(path, "utf8"); - var indent = text.match(/^\s*(?=")/m); - indent = indent && indent[0] || 4; - console.log(indent) - var r = JSON.parse(text); - r = fn(r) || r; - text = JSON.stringify(r, null, indent) + "\n"; - fs.writeFileSync(path, text, "utf8"); - } - - updateJSON("./config.json", function(config) { - var packages = config.packages || (config.packages = {}); - config.packages[name] = { - name: name, - hash: hash, - url: url, - }; - }); - updateJSON("../package.json", function(package) { - var deps = package.dependencies; - console.log(deps[name], hash) - deps[name] = deps[name].replace(/#[a-f\d]*$/i, "#" + hash) - console.log(deps[name], hash) - }); - updateJSON("../npm-shrinkwrap.json", function(package) { - var deps = package.dependencies; - deps[name].from = deps[name].from.replace(/#[a-f\d]*$/i, "#" + hash); - deps[name].resolved = deps[name].resolved.replace(/#[a-f\d]*$/i, "#" + hash); - }); -' - -rm -rf "../node_modules/$NAME" -ln -s `pwd`/$NAME `pwd`/../node_modules/$NAME