299 lines
7.8 KiB
JavaScript
299 lines
7.8 KiB
JavaScript
/*
|
|
Copyright (c) 2013, Oracle and/or its affiliates. All rights
|
|
reserved.
|
|
|
|
This program is free software; you can redistribute it and/or
|
|
modify it under the terms of the GNU General Public License
|
|
as published by the Free Software Foundation; version 2 of
|
|
the License.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program; if not, write to the Free Software
|
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
|
|
02110-1301 USA
|
|
*/
|
|
|
|
// configure.js:
|
|
// Try to find installed mysql that matches architecture of node
|
|
// Ask user for mysql pathname
|
|
// Write mysql pathname into config.gypi and config.waf
|
|
|
|
// TODO: Auto-detect mysql layout here, and write about it in config.gypi
|
|
|
|
"use strict";
|
|
|
|
var fs = require("fs"),
|
|
path = require("path"),
|
|
readline = require("readline");
|
|
|
|
var archbits, archname, archmysql;
|
|
|
|
switch(process.arch) {
|
|
case 'ia32':
|
|
archbits = 32;
|
|
archmysql = 'i686';
|
|
break;
|
|
case 'x64':
|
|
archbits = 64;
|
|
archmysql = 'x86_64';
|
|
break;
|
|
default:
|
|
throw "Architecture " + process.arch + " unsupported.";
|
|
}
|
|
|
|
var path_sep = ( typeof path.sep == 'undefined' ? '/' : path.sep);
|
|
|
|
archname = String(archbits) + '-bit';
|
|
|
|
var lf = '\n';
|
|
|
|
var greeting =
|
|
'# ' +lf+
|
|
'# MySQL Cluster NoSQL API for Node.JS' +lf+
|
|
'# April, 2013' +lf+
|
|
'# ' +lf+
|
|
'# The NoSQL API for Node.JS provides lightweight object mapping for ' +lf+
|
|
'# JavaScript. The API can be used with two separate backend adapters:' +lf+
|
|
'# - The "ndb" adapter, which uses the C++ NDB API to provide' +lf+
|
|
'# high-performance native access to MySQL Cluster. ' +lf+
|
|
'# - The "mysql" adapter, which uses the node-mysql driver ' +lf+
|
|
'# available from http://github.com/felixge/node-mysql' +lf+
|
|
'# ' +lf+
|
|
'# The mysql backend translates API calls into SQL statements and sends ' +lf+
|
|
'# them to a MySQL server. The ndb backend communicates directly with ' +lf+
|
|
'# NDB data nodes, without translating to SQL or making any use of a ' +lf+
|
|
'# MySQL Server.' +lf+
|
|
'# ' +lf+
|
|
'# In order to build and run the ndb adapter, you must have: ' +lf+
|
|
'# - An installation of MySQL Cluster 7.x or MySQL 5.6 ' +lf+
|
|
'# including headers and shared library files [' +archname +']' +lf+
|
|
'# - A working C++ compiler ' +lf+
|
|
'# ' +lf;
|
|
|
|
function verify(dir) {
|
|
var stats;
|
|
try {
|
|
stats = fs.statSync(dir);
|
|
return stats.isDirectory();
|
|
}
|
|
catch(e) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
function get_candidates_windows() {
|
|
var candidates = [];
|
|
var c1 = "C:\\Program Files\\MySQL Server 5.6";
|
|
if(verify(c1)) {
|
|
candidates.push(c1);
|
|
}
|
|
return candidates;
|
|
}
|
|
|
|
|
|
function get_candidates() {
|
|
var candidates = [];
|
|
var link, verified;
|
|
|
|
if(verify('/usr/share/mysql/java')) { // RPM
|
|
candidates.push('/usr');
|
|
}
|
|
|
|
if(verify('/usr/local/mysql/share/java')) { // Mac or generic TAR
|
|
/* if /usr/local/mysql is a symlink, the real directory name must match
|
|
the target architecture */
|
|
try {
|
|
link = fs.readlinkSync('/usr/local/mysql');
|
|
verified = (link.indexOf(archmysql) > 0);
|
|
}
|
|
catch(e) {
|
|
verified = null; // not a symlink
|
|
}
|
|
|
|
if(verified !== false) {
|
|
candidates.push('/usr/local/mysql');
|
|
}
|
|
}
|
|
|
|
if(verify('/opt/mysql/server-5.6/share/java')) { // Debian
|
|
candidates.push('/opt/mysql/server-5.6');
|
|
}
|
|
|
|
return candidates;
|
|
}
|
|
|
|
|
|
function build_prompt(candidates) {
|
|
var i = 0, found = '';
|
|
|
|
if(candidates.length) {
|
|
found = '# ' +lf+
|
|
'# ' +lf+
|
|
'# Choose your preferred mysql install location: ' +lf+
|
|
'# ' +lf;
|
|
|
|
for(i ; i < candidates.length ; i++) {
|
|
found += ' [' + String(i+1) + '] ' + candidates[i] + lf;
|
|
}
|
|
}
|
|
else {
|
|
found = '# ' +lf+
|
|
'# ~~~~~~~~ No '+archname+' MySQL Cluster installations found.' +lf+
|
|
'# ' +lf;
|
|
}
|
|
found += ' [' + String(++i) + '] Choose custom mysql directory' +lf;
|
|
|
|
return found;
|
|
}
|
|
|
|
function finish() {
|
|
console.log("");
|
|
console.log("Now run this command:\n\tnode-gyp configure build -d");
|
|
process.exit(0);
|
|
}
|
|
|
|
function testPath(mysqlPath) {
|
|
// We assert that a path is a valid mysql install true if and only if
|
|
// it contains a mysql-test directory
|
|
var testPath = path.join(mysqlPath.trim(), "mysql-test");
|
|
return verify(testPath);
|
|
}
|
|
|
|
function configure(mysql, layout) {
|
|
if(mysql) {
|
|
layout = ""; // fixme
|
|
var gyp = { "variables" : {"mysql_path":mysql, "mysql_layout":layout}};
|
|
fs.writeFileSync("config.gypi", JSON.stringify(gyp) + "\n", "ascii");
|
|
fs.writeFileSync("config.waf", mysql + "\n", 'ascii');
|
|
finish();
|
|
}
|
|
else {
|
|
process.exit(-1);
|
|
}
|
|
}
|
|
|
|
|
|
// Filename completion
|
|
// Returns [ [array of matches], original substring ]
|
|
function completion(line) {
|
|
var matches = [];
|
|
var files = [];
|
|
var dir, base, stat;
|
|
|
|
function readCurrentDir(dir) {
|
|
files = []; // parent scope
|
|
try {
|
|
files = fs.readdirSync(dir);
|
|
}
|
|
catch(e) {}
|
|
}
|
|
|
|
if(line.slice(-1) == path_sep) {
|
|
dir = line;
|
|
readCurrentDir(dir);
|
|
base = "";
|
|
}
|
|
else {
|
|
dir = path.dirname(line); // returns "." if path is unrooted
|
|
base = path.basename(line);
|
|
readCurrentDir(dir);
|
|
}
|
|
|
|
for(var i = 0; i < files.length ; i++) {
|
|
if(files[i].substring(0,1) !== "." && files[i].match("^" + base)) {
|
|
matches.push(path.join(dir, files[i]));
|
|
}
|
|
}
|
|
|
|
if(matches.length == 1) {
|
|
try {
|
|
stat = fs.statSync(matches[0]);
|
|
if(stat.isDirectory()) matches[0] += path_sep;
|
|
}
|
|
catch(e) {}
|
|
}
|
|
|
|
return [matches, line];
|
|
}
|
|
|
|
|
|
///// ****** MAIN ROUTINE STARTS HERE ****** /////
|
|
function main() {
|
|
var candidates;
|
|
if(process.platform == 'win32')
|
|
candidates = get_candidates_windows();
|
|
else
|
|
candidates = get_candidates();
|
|
var text = build_prompt(candidates);
|
|
var rl = readline.createInterface(process.stdin, process.stdout, completion);
|
|
|
|
function hangup() {
|
|
rl.close();
|
|
process.exit(-1);
|
|
}
|
|
|
|
function onEntry(choice) {
|
|
var range = candidates.length + 1;
|
|
var num = Number(choice);
|
|
|
|
if(num == NaN) { // user skipped straight to pathname entry
|
|
onPath(choice);
|
|
}
|
|
else if(num < 1 || num > range) {
|
|
rl.write("Please enter a number between 1 and " + range + "." + lf);
|
|
rl.write("Hit CTRL-C to exit." +lf);
|
|
rl.prompt(true);
|
|
}
|
|
else if(num === (range - 1)) {
|
|
rl.removeListener('line', onEntry);
|
|
customMode();
|
|
}
|
|
else {
|
|
rl.close();
|
|
configure(candidates[num - 1]);
|
|
}
|
|
}
|
|
|
|
function onPath(mysqlPath) {
|
|
if(testPath(mysqlPath)) {
|
|
rl.close();
|
|
configure(mysqlPath);
|
|
}
|
|
else {
|
|
console.log("ERROR: not a MySQL install tree" + lf);
|
|
rl.prompt(true);
|
|
}
|
|
}
|
|
|
|
function mainMode() {
|
|
rl.setPrompt('Your choice> ', 13);
|
|
rl.on('line', onEntry);
|
|
rl.prompt(true);
|
|
}
|
|
|
|
function customMode() {
|
|
rl.setPrompt('MySQL Install Path> ', 20);
|
|
rl.on('line', onPath);
|
|
rl.prompt(true);
|
|
}
|
|
|
|
/* Start here: */
|
|
rl.write(greeting);
|
|
rl.on('SIGINT', hangup);
|
|
if(candidates.length) {
|
|
rl.write(text);
|
|
mainMode();
|
|
}
|
|
else {
|
|
customMode();
|
|
}
|
|
}
|
|
|
|
|
|
main();
|