diff --git a/script/bootstrap b/script/bootstrap index e9288428b..ae7b8d94f 100755 --- a/script/bootstrap +++ b/script/bootstrap @@ -20,32 +20,34 @@ function executeCommands(commands, done, index) { done(null); } -verifyRequirements(); - -var apmInstallPath = path.resolve(__dirname, '..', 'apm'); -if (!fs.existsSync(apmInstallPath)) +function postVerification() { + var apmInstallPath = path.resolve(__dirname, '..', 'apm'); + if (!fs.existsSync(apmInstallPath)) fs.mkdirSync(apmInstallPath); -if (!fs.existsSync(path.join(apmInstallPath, 'node_modules'))) + if (!fs.existsSync(path.join(apmInstallPath, 'node_modules'))) fs.mkdirSync(path.join(apmInstallPath, 'node_modules')); -var apmPath = path.resolve(__dirname, '..', 'apm', 'node_modules', 'atom-package-manager', 'bin', 'apm') -var apmFlags = process.env.JANKY_SHA1 || process.argv.indexOf('--no-color') !== -1 ? '--no-color' : ''; + var apmPath = path.resolve(__dirname, '..', 'apm', 'node_modules', 'atom-package-manager', 'bin', 'apm') + var apmFlags = process.env.JANKY_SHA1 || process.argv.indexOf('--no-color') !== -1 ? '--no-color' : ''; -var npmPath = path.resolve(__dirname, '..', 'build', 'node_modules', '.bin', 'npm'); -var initialNpmCommand = fs.existsSync(npmPath) ? npmPath : 'npm'; -var npmFlags = ' --userconfig=' + path.resolve('.npmrc') + ' '; + var npmPath = path.resolve(__dirname, '..', 'build', 'node_modules', '.bin', 'npm'); + var initialNpmCommand = fs.existsSync(npmPath) ? npmPath : 'npm'; + var npmFlags = ' --userconfig=' + path.resolve('.npmrc') + ' '; -var packagesToDedupe = ['fs-plus', 'humanize-plus', 'oniguruma', 'roaster', 'season']; -var echoNewLine = process.platform == 'win32' ? 'echo.' : 'echo'; + var packagesToDedupe = ['fs-plus', 'humanize-plus', 'oniguruma', 'roaster', 'season']; + var echoNewLine = process.platform == 'win32' ? 'echo.' : 'echo'; -var commands = [ + var commands = [ {command: initialNpmCommand + npmFlags + 'install --quiet', options: {cwd: path.resolve(__dirname, '..', 'build'), ignoreStdout: true}}, {command: npmPath + npmFlags + 'install --quiet', options: {cwd: apmInstallPath, ignoreStdout: true}}, echoNewLine, apmPath + ' clean ' + apmFlags, apmPath + ' install --quiet ' + apmFlags, apmPath + ' dedupe --quiet ' + apmFlags + ' ' + packagesToDedupe.join(' '), -]; + ]; -process.chdir(path.dirname(__dirname)); -executeCommands(commands, process.exit); + process.chdir(path.dirname(__dirname)); + executeCommands(commands, process.exit); +} + +verifyRequirements(postVerification); diff --git a/script/utils/verify-requirements.js b/script/utils/verify-requirements.js index 1cf84c263..261e56f36 100644 --- a/script/utils/verify-requirements.js +++ b/script/utils/verify-requirements.js @@ -1,9 +1,12 @@ var path = require('path'); var fs = require('fs'); +var cp = require('child_process'); +var execFile = cp.execFile; +var pythonPath = process.env.PYTHON; -module.exports = function() { +module.exports = function(cb) { verifyNode(); - verifyPython27(); + verifyPython27(cb); }; function verifyNode() { @@ -16,17 +19,54 @@ function verifyNode() { } } -function verifyPython27() { - if (process.platform == 'win32') { - var pythonPath = process.env.PYTHON; +function verifyPython27(cb) { + if (process.platform !== 'win32') { + cb(); + } else { + var pythonExecutable; if (!pythonPath) { var systemDrive = process.env.SystemDrive || 'C:\\'; pythonPath = path.join(systemDrive, 'Python27'); + + if (fs.existsSync(pythonPath)) { + pythonExecutable = path.join(pythonPath, 'python'); + } else { + pythonExecutable = 'python'; + } + } else { + pythonExecutable = pythonPath; } - if (!fs.existsSync(pythonPath)) { - console.warn("Python 2.7 is required to build Atom. Python 2.7 must be installed at '" + pythonPath + "' or the PYTHON env var must be set to '/path/to/Python27/python.exe'"); - process.exit(1); - } + checkPythonVersion(pythonExecutable, cb); } } + +function checkPythonVersion (python, cb) { + var pythonRequiredMessage = "Python 2.7 is required to build Atom. Python 2.7 must be installed at '" + pythonPath + "', or the PYTHON env var must be set to '/path/to/Python27/python.exe', or the Python install directory must be in the path."; + + execFile(python, ['-c', 'import platform; print(platform.python_version());'], { env: process.env }, function (err, stdout) { + if (err) { + console.log(pythonRequiredMessage); + process.exit(1); + } + + var version = stdout.trim() + if (~version.indexOf('+')) { + version = version.replace(/\+/g, '') + } + if (~version.indexOf('rc')) { + version = version.replace(/rc(.*)$/ig, '') + } + + // Atom requires python 2.7 or better (but not python 3) for node-gyp + var versionArray = version.split('.').map(function(num) { return +num; }); + var goodPythonVersion = (versionArray[0] === 2 && versionArray[1] >= 7) + if (!goodPythonVersion) { + console.log(pythonRequiredMessage); + process.exit(1); + } + + // Finally, if we've gotten this far, callback to resume the install process. + cb(); + }); +}