blob: 39bfcce36398fa404d44854b8b6867c81368521f [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF
* or more contributor license agreements. See th
* distributed with this work for additional infor
* regarding copyright ownership. The ASF license
* to you under the Apache License, Version 2.0 (t
* "License"); you may not use this file except in
* with the License. You may obtain a copy of the
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to
* software distributed under the License is distr
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS
* KIND, either express or implied. See the Licen
* specific language governing permissions and lim
* under the License.
*/
var childProcess = require('child_process');
var fs = require('fs')
var util = require('util')
var path = require('path')
var packager = module.exports
var cachedGitVersion = null;
packager.computeCommitId = function(callback) {
if (cachedGitVersion) {
callback(cachedGitVersion);
return;
}
var versionFileId = fs.readFileSync('VERSION', { encoding: 'utf8' }).trim();
if (/-dev$/.test(versionFileId) && fs.existsSync('.git')) {
var gitPath = 'git';
var args = 'rev-list HEAD --max-count=1 --abbrev-commit';
childProcess.exec(gitPath + ' ' + args, function(err, stdout, stderr) {
var isWindows = process.platform.slice(0, 3) == 'win';
if (err && isWindows) {
gitPath = '"' + path.join(process.env['ProgramFiles'], 'Git', 'bin', 'git.exe') + '"';
childProcess.exec(gitPath + ' ' + args, function(err, stdout, stderr) {
if (err) {
error(err);
} else {
done(versionFileId + '-' + stdout);
}
});
} else if (err) {
error(err);
} else {
done(versionFileId + '-' + stdout);
}
});
} else {
done(fs.readFileSync('VERSION', { encoding: 'utf8' }));
}
function error(err) {
throw new Error(err);
}
function done(stdout) {
var version = stdout.trim();
cachedGitVersion = version;
callback(version);
};
}
//------------------------------------------------------------------------------
packager.generate = function(platform, useWindowsLineEndings, callback) {
packager.computeCommitId(function(commitId) {
var outFile;
var time = new Date().valueOf();
var libraryRelease = packager.bundle(platform, false, commitId);
// if we are using windows line endings, we will also add the BOM
if(useWindowsLineEndings) {
libraryRelease = "\ufeff" + libraryRelease.split(/\r?\n/).join("\r\n");
}
var libraryDebug = packager.bundle(platform, true, commitId);
time = new Date().valueOf() - time;
if (!fs.existsSync('pkg')) {
fs.mkdirSync('pkg');
}
if(!fs.existsSync('pkg/debug')) {
fs.mkdirSync('pkg/debug');
}
outFile = path.join('pkg', 'cordova.' + platform + '.js');
fs.writeFileSync(outFile, libraryRelease, 'utf8');
outFile = path.join('pkg', 'debug', 'cordova.' + platform + '-debug.js');
fs.writeFileSync(outFile, libraryDebug, 'utf8');
console.log('generated cordova.' + platform + '.js @ ' + commitId + ' in ' + time + 'ms');
callback();
});
}
//------------------------------------------------------------------------------
packager.bundle = function(platform, debug, commitId) {
var modules = collectFiles('lib/common')
var scripts = collectFiles('lib/scripts')
modules[''] = 'lib/cordova.js'
copyProps(modules, collectFiles(path.join('lib', platform)));
if (platform === 'test') {
copyProps(modules, collectFiles(path.join('lib', 'android', 'android'), 'android/'));
}
var output = [];
output.push("// Platform: " + platform);
output.push("// " + commitId);
// write header
output.push('/*', getContents('LICENSE-for-js-file.txt'), '*/')
output.push(';(function() {')
output.push("var CORDOVA_JS_BUILD_LABEL = '" + commitId + "';");
// write initial scripts
if (!scripts['require']) {
throw new Error("didn't find a script for 'require'")
}
writeScript(output, scripts['require'], debug)
// write modules
var moduleIds = Object.keys(modules)
moduleIds.sort()
for (var i=0; i<moduleIds.length; i++) {
var moduleId = moduleIds[i]
writeModule(output, modules[moduleId], moduleId, debug)
}
output.push("window.cordova = require('cordova');")
// write final scripts
if (!scripts['bootstrap']) {
throw new Error("didn't find a script for 'bootstrap'")
}
writeScript(output, scripts['bootstrap'], debug)
var bootstrapPlatform = 'bootstrap-' + platform
if (scripts[bootstrapPlatform]) {
writeScript(output, scripts[bootstrapPlatform], debug)
}
// write trailer
output.push('})();')
return output.join('\n')
}
//------------------------------------------------------------------------------
function collectFile(dir, id, entry) {
if (!id) id = ''
var moduleId = path.join(id, entry)
var fileName = path.join(dir, entry)
var stat = fs.statSync(fileName)
var result = {};
moduleId = getModuleId(moduleId)
result[moduleId] = fileName
return copyProps({}, result)
}
function collectFiles(dir, id) {
if (!id) id = ''
var result = {}
var entries = fs.readdirSync(dir)
entries = entries.filter(function(entry) {
if (entry.match(/\.js$/)) return true
var stat = fs.statSync(path.join(dir, entry))
if (stat.isDirectory()) return true
})
entries.forEach(function(entry) {
var moduleId = path.join(id, entry)
var fileName = path.join(dir, entry)
var stat = fs.statSync(fileName)
if (stat.isDirectory()) {
copyProps(result, collectFiles(fileName, moduleId))
}
else {
moduleId = getModuleId(moduleId)
result[moduleId] = fileName
}
})
return copyProps({}, result)
}
//------------------------------------------------------------------------------
function writeScript(oFile, fileName, debug) {
var contents = getContents(fileName, 'utf8')
contents = stripHeader(contents, fileName);
writeContents(oFile, fileName, contents, debug);
}
//------------------------------------------------------------------------------
function writeModule(oFile, fileName, moduleId, debug) {
var contents = getContents(fileName, 'utf8')
contents = '\n' + stripHeader(contents, fileName) + '\n'
// Windows fix, '\' is an escape, but defining requires '/' -jm
moduleId = path.join('cordova', moduleId).split("\\").join("/");
var signature = 'function(require, exports, module)';
contents = 'define("' + moduleId + '", ' + signature + ' {' + contents + '});\n'
writeContents(oFile, fileName, contents, debug)
}
//------------------------------------------------------------------------------
function getContents(file) {
return fs.readFileSync(file, 'utf8');
}
//------------------------------------------------------------------------------
function writeContents(oFile, fileName, contents, debug) {
if (debug) {
contents += '\n//@ sourceURL=' + fileName
contents = 'eval(' + JSON.stringify(contents) + ')'
// this bit makes it easier to identify modules
// with syntax errors in them
var handler = 'console.log("exception: in ' + fileName + ': " + e);'
handler += 'console.log(e.stack);'
contents = 'try {' + contents + '} catch(e) {' + handler + '}'
}
else {
contents = '// file: ' + fileName.split("\\").join("/") + '\n' + contents;
}
oFile.push(contents)
}
//------------------------------------------------------------------------------
function getModuleId(fileName) {
return fileName.match(/(.*)\.js$/)[1]
}
//------------------------------------------------------------------------------
function copyProps(target, source) {
for (var key in source) {
if (!source.hasOwnProperty(key)) continue
target[key] = source[key]
}
return target
}
//-----------------------------------------------------------------------------
// Strips the license header. Basically only the first multi-line comment up to to the closing */
function stripHeader(contents, fileName) {
var ls = contents.split(/\r?\n/);
while (ls[0]) {
if (ls[0].match(/^\s*\/\*/) || ls[0].match(/^\s*\*/)) {
ls.shift();
}
else if (ls[0].match(/^\s*\*\//)) {
ls.shift();
break;
}
else {
console.log("WARNING: file name " + fileName + " is missing the license header");
break;
}
}
return ls.join('\n');
}