338 lines
8.5 KiB
JavaScript
338 lines
8.5 KiB
JavaScript
/*
|
|
Copyright (c) 2013, 2016, 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, version 2.0,
|
|
as published by the Free Software Foundation.
|
|
|
|
This program is also distributed with certain software (including
|
|
but not limited to OpenSSL) that is licensed under separate terms,
|
|
as designated in a particular file or component or in included license
|
|
documentation. The authors of MySQL hereby grant you an additional
|
|
permission to link the program and your derivative works with the
|
|
separately licensed software that they have included with MySQL.
|
|
|
|
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, version 2.0, 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:
|
|
// If "-m /path/to/mysql/tree" is specified, configure jones-ndb to
|
|
// build with that mysql.
|
|
// Otherwise, run interactively:
|
|
// Try to find installed mysql that matches architecture of node
|
|
// Ask user for mysql pathname
|
|
//
|
|
// Writes mysql pathname and other options into config.gypi
|
|
//
|
|
|
|
// 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 = ( path.sep === undefined ? '/' : path.sep);
|
|
|
|
archname = String(archbits) + '-bit';
|
|
|
|
var lf = '\n';
|
|
|
|
var greeting =
|
|
'# ' +lf+
|
|
'# MySQL Cluster Driver for Jones' +lf+
|
|
'# ' +lf+
|
|
'# This Driver provides high-performance native access to MySQL Cluster ' +lf+
|
|
'# using the NDB API.' +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("");
|
|
// The -d in the following line configures a debug build
|
|
// It is strictly necessary only on Windows platforms
|
|
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 tree if and only if
|
|
// it contains a mysql-test directory
|
|
return verify(path.join(mysqlPath.trim(), "mysql-test"));
|
|
}
|
|
|
|
function configure(mysql, layout) {
|
|
if(mysql) {
|
|
var gyp = {};
|
|
gyp.variables = { "mysql_path" : mysql,
|
|
"mysql_layout" : layout || "",
|
|
"node_version" : process.versions.node
|
|
};
|
|
fs.writeFileSync("config.gypi", JSON.stringify(gyp) + "\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, i;
|
|
|
|
function readCurrentDir(dir) {
|
|
files = []; // parent scope
|
|
try {
|
|
files = fs.readdirSync(dir);
|
|
}
|
|
catch(ignore) {}
|
|
}
|
|
|
|
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(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(ignore) {}
|
|
}
|
|
|
|
return [matches, line];
|
|
}
|
|
|
|
|
|
///// ****** INTERACTIVE MAIN ROUTINE STARTS HERE ****** /////
|
|
function interactive_main(options) {
|
|
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 onPath(mysqlPath) {
|
|
if(testPath(mysqlPath)) {
|
|
rl.close();
|
|
configure(mysqlPath);
|
|
}
|
|
else {
|
|
console.log("ERROR: not a MySQL install tree" + lf);
|
|
rl.prompt(true);
|
|
}
|
|
}
|
|
|
|
function customMode() {
|
|
rl.setPrompt('MySQL Install Path> ', 20);
|
|
rl.on('line', onPath);
|
|
rl.prompt(true);
|
|
}
|
|
|
|
function onEntry(choice) {
|
|
var range = candidates.length + 1;
|
|
var num = Number(choice);
|
|
|
|
if(isNaN(num)) { // 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 mainMode() {
|
|
rl.setPrompt('Your choice> ', 13);
|
|
rl.on('line', onEntry);
|
|
rl.prompt(true);
|
|
}
|
|
|
|
/* Start here: */
|
|
|
|
/* MySQL Path was supplied on the command line */
|
|
if(process.argv[2]) {
|
|
configure(process.argv[2]);
|
|
}
|
|
|
|
/* Get path interactively */
|
|
rl.write(greeting);
|
|
rl.on('SIGINT', hangup);
|
|
if(candidates.length) {
|
|
rl.write(text);
|
|
mainMode();
|
|
}
|
|
else {
|
|
customMode();
|
|
}
|
|
}
|
|
|
|
function process_options() {
|
|
var i, len, opts;
|
|
len = process.argv.length;
|
|
opts = { "interactive" : true };
|
|
for(i = 2 ; i < len ; i++) {
|
|
if(process.argv[i] == "-m" && (i+1 < len)) {
|
|
opts.interactive = false;
|
|
opts.path = process.argv[i+1];
|
|
}
|
|
}
|
|
return opts;
|
|
}
|
|
|
|
function utility_main(options) {
|
|
if(verify(options.path)) {
|
|
configure(options.path);
|
|
} else {
|
|
console.log("ERROR: " + options.path + " is not a directory.");
|
|
process.exit(-1);
|
|
}
|
|
}
|
|
|
|
/* Script starts here: */
|
|
var opts = process_options();
|
|
|
|
if(opts.interactive) {
|
|
interactive_main(opts);
|
|
} else {
|
|
utility_main(opts);
|
|
}
|
|
|