function detectModules(searchPaths, config, logger, callback) {
	var results = {},
		zipRegExp = /^.+\-.+?\-.+?\.zip$/,
		osNamesRegExp = /^osx|win32|linux$/,
		ignoreDirs = new RegExp(config && config.get('cli.ignoreDirs') || '^(.svn|.git|.hg|.?[Cc][Vv][Ss]|.bzr)$');

	Array.isArray(searchPaths) || (searchPaths = [searchPaths]);

	async.parallel(searchPaths.map(function (modulesDir) {
		return function(cb) {
			if (!fs.existsSync(modulesDir)) return cb();

			var moduleRoot = path.join(modulesDir, '..'),
				tasks = [];

			// auto-install zipped modules
			fs.readdirSync(moduleRoot).forEach(function (file) {
				var moduleZip = path.join(moduleRoot, file);
				if (fs.existsSync(moduleZip) && fs.statSync(moduleZip).isFile() && zipRegExp.test(file)) {
					tasks.push(function (taskDone) {
						logger && logger.info(__('Installing module: %s', file));
						zip.unzip(moduleZip, moduleRoot, null, function (err) {
							if (err) {
								logger && logger.error(__('Failed to unzip module "%s"', moduleZip));
							} else {
								fs.unlinkSync(moduleZip);
							}
							taskDone();
						});
					});
				}
			});

			async.parallel(tasks, function () {
				if (!fs.existsSync(modulesDir)) return cb();

				logger && logger.debug(__('Detecting modules in %s', modulesDir.cyan));

				// loop through platforms
				fs.readdirSync(modulesDir).forEach(function (platform) {
					var modulesPath = path.join(modulesDir, platform);
					if (fs.existsSync(modulesPath) && fs.statSync(modulesPath).isDirectory() && !osNamesRegExp.test(platform) && !ignoreDirs.test(platform)) {
						// loop through module names
						fs.readdirSync(modulesPath).forEach(function (moduleName) {
							var modulePath = path.join(modulesPath, moduleName);
							if (fs.existsSync(modulePath) && fs.statSync(modulePath).isDirectory() && !ignoreDirs.test(moduleName)) {
								// loop through versions
								fs.readdirSync(modulePath).forEach(function (ver) {
									if (ignoreDirs.test(ver)) return;
									var versionPath = path.join(modulePath, ver),
										manifestFile = path.join(versionPath, 'manifest');
									if (fs.existsSync(versionPath) && fs.statSync(versionPath).isDirectory() && fs.existsSync(manifestFile)) {
										var dest = results[platform] || (results[platform] = {}),
											mod = dest[moduleName] || (dest[moduleName] = {});

										if (!mod[ver]) {
											mod[ver] = {
												modulePath: versionPath,
												version: ver,
												manifest: {}
											};

											fs.readFileSync(manifestFile).toString().split('\n').forEach(function (line) {
												var p = line.indexOf(':');
												if (line.charAt(0) != '#' && p != -1) {
													mod[ver].manifest[line.substring(0, p)] = line.substring(p + 1).trim();
												}
											});

											logger && logger.debug(__('Detected %s module: %s %s @ %s', platform, mod[ver].manifest.moduleid.cyan, ver, mod[ver].modulePath));
										}
									}
								});
							}
						});
					}
				});

				cb();
			});
		};
	}), function (err) {
		callback(err, results);
	});
}
/**
 * Searches an array of paths for Titanium modules. If it encounters a zip file
 * that matches module zip filename pattern, it will automatically unzip it and
 * remove the zip file prior to detecting modules.
 * @param {Array<String>} searchPaths - An array of paths to search for Titanium modules
 * @param {Object} config - The CLI config
 * @param {Object} logger - A logger instance
 * @param {Function} callback - A function to call when done
 * @private
 */
Searches an array of paths for Titanium modules. If it encounters a zip file
that matches module zip filename pattern, it will automatically unzip it and
remove the zip file prior to detecting modules.
Searches an array of paths for Titanium modules . If it encounters a zip file that matches module zip filename pattern it will automatically unzip it and remove the zip file prior to detecting modules .
function detectModules(searchPaths, config, logger, callback) {
	var results = {},
		zipRegExp = /^.+\-.+?\-.+?\.zip$/,
		osNamesRegExp = /^osx|win32|linux$/,
		ignoreDirs = new RegExp(config && config.get('cli.ignoreDirs') || '^(.svn|.git|.hg|.?[Cc][Vv][Ss]|.bzr)$');
	Array.isArray(searchPaths) || (searchPaths = [searchPaths]);
	async.parallel(searchPaths.map(function (modulesDir) {
		return function(cb) {
			if (!fs.existsSync(modulesDir)) return cb();
			var moduleRoot = path.join(modulesDir, '..'),
				tasks = [];
			fs.readdirSync(moduleRoot).forEach(function (file) {
				var moduleZip = path.join(moduleRoot, file);
				if (fs.existsSync(moduleZip) && fs.statSync(moduleZip).isFile() && zipRegExp.test(file)) {
					tasks.push(function (taskDone) {
						logger && logger.info(__('Installing module: %s', file));
						zip.unzip(moduleZip, moduleRoot, null, function (err) {
							if (err) {
								logger && logger.error(__('Failed to unzip module "%s"', moduleZip));
							} else {
								fs.unlinkSync(moduleZip);
							}
							taskDone();
						});
					});
				}
			});
			async.parallel(tasks, function () {
				if (!fs.existsSync(modulesDir)) return cb();
				logger && logger.debug(__('Detecting modules in %s', modulesDir.cyan));
				fs.readdirSync(modulesDir).forEach(function (platform) {
					var modulesPath = path.join(modulesDir, platform);
					if (fs.existsSync(modulesPath) && fs.statSync(modulesPath).isDirectory() && !osNamesRegExp.test(platform) && !ignoreDirs.test(platform)) {
						fs.readdirSync(modulesPath).forEach(function (moduleName) {
							var modulePath = path.join(modulesPath, moduleName);
							if (fs.existsSync(modulePath) && fs.statSync(modulePath).isDirectory() && !ignoreDirs.test(moduleName)) {
								fs.readdirSync(modulePath).forEach(function (ver) {
									if (ignoreDirs.test(ver)) return;
									var versionPath = path.join(modulePath, ver),
										manifestFile = path.join(versionPath, 'manifest');
									if (fs.existsSync(versionPath) && fs.statSync(versionPath).isDirectory() && fs.existsSync(manifestFile)) {
										var dest = results[platform] || (results[platform] = {}),
											mod = dest[moduleName] || (dest[moduleName] = {});
										if (!mod[ver]) {
											mod[ver] = {
												modulePath: versionPath,
												version: ver,
												manifest: {}
											};
											fs.readFileSync(manifestFile).toString().split('\n').forEach(function (line) {
												var p = line.indexOf(':');
												if (line.charAt(0) != '#' && p != -1) {
													mod[ver].manifest[line.substring(0, p)] = line.substring(p + 1).trim();
												}
											});
											logger && logger.debug(__('Detected %s module: %s %s @ %s', platform, mod[ver].manifest.moduleid.cyan, ver, mod[ver].modulePath));
										}
									}
								});
							}
						});
					}
				});
				cb();
			});
		};
	}), function (err) {
		callback(err, results);
	});
}
function detectModules ( searchPaths , config , logger , callback ) { var results = { } , zipRegExp = / ^.+\-.+?\-.+?\.zip$ / , osNamesRegExp = / ^osx|win32|linux$ / , ignoreDirs = new RegExp ( config && config . get ( 'cli.ignoreDirs' ) || '^(.svn|.git|.hg|.?[Cc][Vv][Ss]|.bzr)$' ) ; Array . isArray ( searchPaths ) || ( searchPaths = [ searchPaths ] ) ; async . parallel ( searchPaths . map ( function ( modulesDir ) { return function ( cb ) { if ( ! fs . existsSync ( modulesDir ) ) return cb ( ) ; var moduleRoot = path . join ( modulesDir , '..' ) , tasks = [ ] ; fs . readdirSync ( moduleRoot ) . forEach ( function ( file ) { var moduleZip = path . join ( moduleRoot , file ) ; if ( fs . existsSync ( moduleZip ) && fs . statSync ( moduleZip ) . isFile ( ) && zipRegExp . test ( file ) ) { tasks . push ( function ( taskDone ) { logger && logger . info ( __ ( 'Installing module: %s' , file ) ) ; zip . unzip ( moduleZip , moduleRoot , null , function ( err ) { if ( err ) { logger && logger . error ( __ ( 'Failed to unzip module "%s"' , moduleZip ) ) ; } else { fs . unlinkSync ( moduleZip ) ; } taskDone ( ) ; } ) ; } ) ; } } ) ; async . parallel ( tasks , function ( ) { if ( ! fs . existsSync ( modulesDir ) ) return cb ( ) ; logger && logger . debug ( __ ( 'Detecting modules in %s' , modulesDir . cyan ) ) ; fs . readdirSync ( modulesDir ) . forEach ( function ( platform ) { var modulesPath = path . join ( modulesDir , platform ) ; if ( fs . existsSync ( modulesPath ) && fs . statSync ( modulesPath ) . isDirectory ( ) && ! osNamesRegExp . test ( platform ) && ! ignoreDirs . test ( platform ) ) { fs . readdirSync ( modulesPath ) . forEach ( function ( moduleName ) { var modulePath = path . join ( modulesPath , moduleName ) ; if ( fs . existsSync ( modulePath ) && fs . statSync ( modulePath ) . isDirectory ( ) && ! ignoreDirs . test ( moduleName ) ) { fs . readdirSync ( modulePath ) . forEach ( function ( ver ) { if ( ignoreDirs . test ( ver ) ) return ; var versionPath = path . join ( modulePath , ver ) , manifestFile = path . join ( versionPath , 'manifest' ) ; if ( fs . existsSync ( versionPath ) && fs . statSync ( versionPath ) . isDirectory ( ) && fs . existsSync ( manifestFile ) ) { var dest = results [ platform ] || ( results [ platform ] = { } ) , mod = dest [ moduleName ] || ( dest [ moduleName ] = { } ) ; if ( ! mod [ ver ] ) { mod [ ver ] = { modulePath : versionPath , version : ver , manifest : { } } ; fs . readFileSync ( manifestFile ) . toString ( ) . split ( '\n' ) . forEach ( function ( line ) { var p = line . indexOf ( ':' ) ; if ( line . charAt ( 0 ) != '#' && p != - 1 ) { mod [ ver ] . manifest [ line . substring ( 0 , p ) ] = line . substring ( p + 1 ) . trim ( ) ; } } ) ; logger && logger . debug ( __ ( 'Detected %s module: %s %s @ %s' , platform , mod [ ver ] . manifest . moduleid . cyan , ver , mod [ ver ] . modulePath ) ) ; } } } ) ; } } ) ; } } ) ; cb ( ) ; } ) ; } ; } ) , function ( err ) { callback ( err , results ) ; } ) ; }
Searches an array of paths for Titanium modules.
Searches an array of paths for Titanium modules .
// auto-install zipped modules // loop through platforms // loop through module names // loop through versions