define([ "require", "dojo/_base/lang", "./argv", "./fs", "./fileUtils", "./buildControlDefault", "./v1xProfiles", "./stringify", "./process", "./messages", "dojo/text!./help.txt" ], function(require, lang, argv, fs, fileUtils, bc, v1xProfiles, stringify, process, messages, helpText){ // // Process the arguments given on the command line to build up a profile object that is used to instruct and control // the build process. // // This modules is a bit tedious. Is methodically goes through each option set, cleaning and conditioning user input making it // easy to use for the remainder of the program. Readers are advised to tackle it top-to-bottom. There is no magic...just // a whole bunch of imperative programming. // if(!isNaN(argv)){ // if argv is a number, then it's an exit code bc.exitCode = argv; return bc; } eval(require.scopeify("./fs, ./fileUtils, ./v1xProfiles")); var isString = function(it){ return typeof it === "string"; }, isNonemptyString = function(it){ return isString(it) && it.length; }, isDefined = function(it){ return typeof it !="undefined"; }, cleanupFilenamePair = function(item, srcBasePath, destBasePath, hint){ var result; if(isString(item)){ result = [computePath(item, srcBasePath), computePath(item, destBasePath)]; }else{ result = [computePath(item[0], srcBasePath), computePath(item[1], destBasePath)].concat(item.slice(2)); } if(!isAbsolutePath(result[0]) || !isAbsolutePath(result[1])){ bc.log("inputInvalidPath", ["path", item, "hint", hint]); } return result; }, slashTerminate = function(path){ return path + /\/$/.test(path) ? "" : "/"; }, isEmpty = function(it){ for(var p in it) return false; return true; }, cleanDeprecated = function(o, inputFile){ var deprecated = []; for(p in o){ if(/^(log|loader|xdDojoPath|scopeDjConfig|xdScopeArgs|xdDojoScopeName|expandProvide|buildLayers|query|removeDefaultNameSpaces|addGuards)$/.test(p)){ deprecated.push(p); bc.log("inputDeprecated", ["switch", p, inputFile]); } } deprecated.forEach(function(p){ delete o[p]; }); }, mix = function(dest, src){ dest = dest || {}; src = src || {}; for(var p in src) dest[p] = src[p]; return dest; }, mixPackage = function(packageInfo){ var name = packageInfo.name; bc.packageMap[name] = mix(bc.packageMap[name], packageInfo); }, // mix a profile object into the global profile object mixProfileObject = function(src){ cleanDeprecated(src, src.selfFilename); // the profile properties... // paths, plugins, transforms, staticHasFeatures // ...are mixed one level deep; messageCategories, messages, packages, and packagePaths require special handling; all others are over-written // FIXME: the only way to modify the transformJobs vector is to create a whole new vector? for(var p in src){ if(!/paths|plugins|messages|transforms|staticHasFeatures|packages|packagePaths|defaultConfig/.test(p)){ bc[p] = src[p]; } } // the one-level-deep mixers ["paths","plugins","transforms","staticHasFeatures"].forEach(function(p){ bc[p] = mix(bc[p], src[p]); }); // messages require special handling if(src.messageCategories){ for(p in src.messageCategories){ bc.addCategory(p, src.messageCategories[p]); } } (src.messages || []).forEach(function(item){bc.addMessage.apply(bc, item);}); // packagePaths and packages require special processing to get their contents into packageMap; do that first... // process packagePaths before packages before packageMap since packagePaths is less specific than // packages is less specific than packageMap. Notice that attempts to edit an already-existing package // only edits specific package properties given (see mixPackage, above) for(var base in src.packagePaths){ src.packagePaths[base].forEach(function(packageInfo){ if(isString(packageInfo)){ packageInfo = {name:packageInfo}; } packageInfo.location = catPath(base, packageInfo.name); mixPackage(packageInfo); }); }; (src.packages || []).forEach(function(packageInfo){ if(isString(packageInfo)){ packageInfo = {name:packageInfo}; } mixPackage(packageInfo); }); // defaultConfig requires special handling for(p in src.defaultConfig){ if(p=="hasCache"){ mix(bc.defaultConfig.hasCache, src.defaultConfig.hasCache); }else{ bc.defaultConfig[p] = src.defaultConfig[p]; } } }; argv.args.profiles.forEach(function(item){ var temp = mix({}, item), build = item.build; delete temp.build; mixProfileObject(temp); build && mixProfileObject(build); }); cleanDeprecated(argv.args, "command line"); // lastly, explicit command line switches override any evaluated profile objects for(var argName in argv.args) if(argName!="profiles"){ bc[argName] = argv.args[argName]; } // at this point the raw profile object has been fully initialized; clean it up and look for errors... bc.basePath = computePath(bc.basePath, process.cwd()); var releaseDir = catPath(bc.releaseDir || "../release", bc.releaseName || ""); bc.destBasePath = computePath(releaseDir, bc.basePath); // compute global copyright, if any bc.copyright = isNonemptyString(bc.copyright) ? (maybeRead(computePath(bc.copyright, bc.basePath)) || bc.copyright) : ""; bc.copyrightLayers = !!bc.copyrightLayers; bc.copyrightNonlayers = !!bc.copyrightNonlayers; // compute files, dirs, and trees (function(){ for(var property in {files:1, dirs:1, trees:1}){ if(bc[property] instanceof Array){ bc[property] = bc[property].map(function(item){ return cleanupFilenamePair(item, bc.basePath, bc.destBasePath, property); }); } } })(); // cleanup the replacements (if any) (function(){ var cleanSet = {}, src, dest; for(src in bc.replacements){ cleanSet[computePath(src, bc.basePath)] = bc.replacements[src]; } bc.replacements = cleanSet; })(); // explicit mini and/or copyTests wins; explicit copyTests ignores explicit mini if(!("mini" in bc)){ bc.mini = true; } if(!("copyTests" in bc)){ bc.copyTests = !bc.mini; } if(isString(bc.copyTests)){ bc.copyTests = bc.copyTests.toLowerCase(); } if(bc.copyTests!="build"){ // convert to pure boolean bc.copyTests = !!bc.copyTests; } function getDiscreteLocales(locale){ for(var locales = locale.split("-"), result = [], current = "", i = 0; i