/Tools/capp/Generate.j
http://github.com/cacaodev/cappuccino · Unknown · 498 lines · 393 code · 105 blank · 0 comment · 0 complexity · 55ca7c99979f05496504c503f25ae92b MD5 · raw file
- /*
- * Generate.j
- * capp
- *
- * Created by Francisco Tolmasky.
- * Copyright 2009, 280 North, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
- @import "Configuration.j"
- var OS = require("os"),
- SYSTEM = require("system"),
- FILE = require("file"),
- OBJJ = require("objective-j"),
- stream = require("narwhal/term").stream,
- parser = new (require("narwhal/args").Parser)();
- parser.usage("DESTINATION_DIRECTORY");
- parser.help("Generate a Cappuccino project or Frameworks directory");
- parser.option("-t", "--template", "template")
- .set()
- .def("Application")
- .help("Selects a project template to use (default: Application).");
- parser.option("-f", "--frameworks", "justFrameworks")
- .set(true)
- .help("Only generate or update Frameworks directory.");
- parser.option("-F", "--framework", "framework", "frameworks")
- .def([])
- .push()
- .help("Additional framework to copy/symlink (default: Objective-J, Foundation, AppKit)");
- parser.option("-T", "--theme", "theme", "themes")
- .def([])
- .push()
- .help("Additional Theme to copy/symlink into Resource (default: nothing)");
- parser.option("--no-frameworks", "noFrameworks")
- .set(true)
- .help("Don't copy any default frameworks (can be overridden with -F)");
- parser.option("--symlink", "symlink")
- .set(true)
- .help("Creates a symlink to each framework instead of copying.");
- parser.option("--build", "useCappBuild")
- .set(true)
- .help("Uses frameworks in the $CAPP_BUILD.");
- parser.option("-l")
- .action(function(o) { o.symlink = o.useCappBuild = true; })
- .help("Enables both the --symlink and --build options.");
- parser.option("--force", "force")
- .set(true)
- .help("Overwrite update existing frameworks.");
- parser.option("--noconfig", "noconfig")
- .set(true)
- .help("Use the default configuration, ignore your configuration.");
- parser.option("--list-templates", "listTemplates")
- .set(true)
- .help("Lists available templates.");
- parser.option("--list-frameworks", "listFrameworks")
- .set(true)
- .help("Lists available frameworks.");
- parser.helpful();
- // FIXME: better way to do this:
- var CAPP_HOME = require("narwhal/packages").catalog["cappuccino"].directory,
- templatesDirectory = FILE.join(CAPP_HOME, "lib", "capp", "Resources", "Templates");
- function gen(/*va_args*/)
- {
- var args = ["capp gen"].concat(Array.prototype.slice.call(arguments)),
- options = parser.parse(args, null, null, true);
- if (options.args.length > 1)
- {
- parser.printUsage(options);
- OS.exit(1);
- }
- if (options.listTemplates)
- {
- listTemplates();
- return;
- }
- if (options.listFrameworks)
- {
- listFrameworks();
- return;
- }
- var destination = options.args[0];
- if (!destination)
- {
- if (options.justFrameworks)
- destination = ".";
- else
- {
- parser.printUsage(options);
- OS.exit(1);
- }
- }
- var sourceTemplate = null;
- if (FILE.isAbsolute(options.template))
- sourceTemplate = options.template;
- else
- sourceTemplate = FILE.join(templatesDirectory, options.template);
- if (!FILE.isDirectory(sourceTemplate))
- {
- stream.print(colorize("Error: ", "red") + "The template " + logPath(sourceTemplate) + " cannot be found. Available templates are:");
- listTemplates();
- OS.exit(1);
- }
- var configFile = FILE.join(sourceTemplate, "template.config"),
- config = {};
- if (FILE.isFile(configFile))
- config = JSON.parse(FILE.read(configFile, { charset:"UTF-8" }));
- var destinationProject = destination,
- configuration = options.noconfig ? [Configuration defaultConfiguration] : [Configuration userConfiguration],
- frameworks = options.frameworks,
- themes = options.themes;
- if (!options.noFrameworks)
- frameworks.push("Objective-J", "Foundation", "AppKit");
- if (options.justFrameworks)
- {
- createFrameworksInFile(frameworks, destinationProject, options.symlink, options.useCappBuild, options.force);
- createThemesInFile(themes, destinationProject, options.symlink, options.force);
- }
- else if (!FILE.exists(destinationProject))
- {
- // FIXME???
- FILE.copyTree(sourceTemplate, destinationProject);
- var files = FILE.glob(FILE.join(destinationProject, "**", "*")),
- count = files.length,
- name = FILE.basename(destinationProject),
- orgIdentifier = [configuration valueForKey:@"organization.identifier"] || "";
- [configuration setTemporaryValue:name forKey:@"project.name"];
- [configuration setTemporaryValue:orgIdentifier + '.' + toIdentifier(name) forKey:@"project.identifier"];
- [configuration setTemporaryValue:toIdentifier(name) forKey:@"project.nameasidentifier"];
- for (var index = 0; index < count; ++index)
- {
- var path = files[index];
- if (FILE.isDirectory(path))
- continue;
- if (FILE.basename(path) === ".DS_Store")
- continue;
- // Don't do this for images.
- if ([".png", ".jpg", ".jpeg", ".gif", ".tif", ".tiff"].indexOf(FILE.extension(path).toLowerCase()) !== -1)
- continue;
- try
- {
- var contents = FILE.read(path, { charset : "UTF-8" }),
- key = null,
- keyEnumerator = [configuration keyEnumerator];
- while ((key = [keyEnumerator nextObject]) !== nil)
- contents = contents.replace(new RegExp("__" + RegExp.escape(key) + "__", 'g'), [configuration valueForKey:key]);
- FILE.write(path, contents, { charset: "UTF-8"});
- }
- catch (anException)
- {
- warn("An error occurred (" + anException.toString() + ") while applying the " + (options.noconfig ? "default" : "user") + " configuration to: " + logPath(path));
- }
- }
- var frameworkDestination = destinationProject;
- if (config.FrameworksPath)
- frameworkDestination = FILE.join(frameworkDestination, config.FrameworksPath);
- createFrameworksInFile(frameworks, frameworkDestination, options.symlink, options.useCappBuild);
- var themeDestination = destinationProject;
- if (themes.length)
- createThemesInFile(themes, themeDestination, options.symlink);
- }
- else
- {
- fail("The directory " + FILE.absolute(destinationProject) + " already exists.");
- }
- executePostInstallScript(destinationProject);
- }
- function createFrameworksInFile(/*Array*/ frameworks, /*String*/ aFile, /*Boolean*/ symlink, /*Boolean*/ build, /*Boolean*/ force)
- {
- var destination = FILE.path(FILE.absolute(aFile));
- if (!destination.isDirectory())
- fail("Cannot create Frameworks. The directory does not exist: " + destination);
- var destinationFrameworks = destination.join("Frameworks"),
- destinationDebugFrameworks = destination.join("Frameworks", "Debug");
- stream.print("Creating Frameworks directory in " + logPath(destinationFrameworks) + "...");
- //destinationFrameworks.mkdirs(); // redundant
- destinationDebugFrameworks.mkdirs();
- if (build)
- {
- if (!(SYSTEM.env["CAPP_BUILD"]))
- fail("$CAPP_BUILD must be defined to use the --build or -l option.");
- var builtFrameworks = FILE.path(SYSTEM.env["CAPP_BUILD"]),
- sourceFrameworks = builtFrameworks.join("Release"),
- sourceDebugFrameworks = builtFrameworks.join("Debug");
- frameworks.forEach(function(framework)
- {
- installFramework(sourceFrameworks.join(framework), destinationFrameworks.join(framework), force, symlink);
- installFramework(sourceDebugFrameworks.join(framework), destinationDebugFrameworks.join(framework), force, symlink);
- });
- }
- else
- {
- // Frameworks. Search frameworks paths
- frameworks.forEach(function(framework)
- {
- // Need a special case for Objective-J
- if (framework === "Objective-J")
- {
- // Objective-J. Take from OBJJ_HOME.
- var objjHome = FILE.path(OBJJ.OBJJ_HOME),
- objjPath = objjHome.join("Frameworks", "Objective-J"),
- objjDebugPath = objjHome.join("Frameworks", "Debug", "Objective-J");
- installFramework(objjPath, destinationFrameworks.join("Objective-J"), force, symlink);
- installFramework(objjDebugPath, destinationDebugFrameworks.join("Objective-J"), force, symlink);
- return;
- }
- var found = false;
- for (var i = 0; i < OBJJ.objj_frameworks.length; i++)
- {
- var sourceFramework = FILE.path(OBJJ.objj_frameworks[i]).join(framework);
- if (FILE.isDirectory(sourceFramework))
- {
- installFramework(sourceFramework, destinationFrameworks.join(framework), force, symlink);
- found = true;
- break;
- }
- }
- if (!found)
- warn("Couldn't find the framework: " + logPath(framework));
- for (var i = 0, found = false; i < OBJJ.objj_debug_frameworks.length; i++)
- {
- var sourceDebugFramework = FILE.path(OBJJ.objj_debug_frameworks[i]).join(framework);
- if (FILE.isDirectory(sourceDebugFramework))
- {
- installFramework(sourceDebugFramework, destinationDebugFrameworks.join(framework), force, symlink);
- found = true;
- break;
- }
- }
- if (!found)
- warn("Couldn't find the debug framework: " + logPath(framework));
- });
- }
- }
- function installFramework(source, dest, force, symlink)
- {
- if (dest.exists())
- {
- if (force)
- dest.rmtree();
- else
- {
- warn(logPath(dest) + " already exists. Use --force to overwrite.");
- return;
- }
- }
- if (source.exists())
- {
- stream.print((symlink ? "Symlinking " : "Copying ") + logPath(source) + " ==> " + logPath(dest));
- if (symlink)
- FILE.symlink(source, dest);
- else
- FILE.copyTree(source, dest);
- }
- else
- warn("Cannot find: " + logPath(source));
- }
- function createThemesInFile(/*Array*/ themes, /*String*/ aFile, /*Boolean*/ symlink, /*Boolean*/ force)
- {
- var destination = FILE.path(FILE.absolute(aFile));
- if (!destination.isDirectory())
- fail("Cannot create Themes. The directory does not exist: " + destination);
- var destinationThemes = destination.join("Resources");
- stream.print("Creating Themes in " + logPath(destinationThemes) + "...");
- if (!(SYSTEM.env["CAPP_BUILD"]))
- fail("$CAPP_BUILD must be defined to use the --theme or -T option.");
- var themesBuild = FILE.join(SYSTEM.env["CAPP_BUILD"], "Release"),
- sources = [];
- themes.forEach(function(theme)
- {
- var themeFolder = theme + ".blend",
- path = FILE.join(themesBuild, themeFolder);
- if (!FILE.isDirectory(path))
- fail("Cannot find theme " + themeFolder + " in " + themesBuild);
- sources.push([FILE.path(path), themeFolder])
- });
- sources.forEach(function(source)
- {
- installTheme(source[0], FILE.path(destinationThemes).join(source[1]), force, symlink);
- });
- }
- function installTheme(source, dest, force, symlink)
- {
- if (dest.exists())
- {
- if (force)
- dest.rmtree();
- else
- {
- warn(logPath(dest) + " already exists. Use --force to overwrite.");
- return;
- }
- }
- if (source.exists())
- {
- stream.print((symlink ? "Symlinking " : "Copying ") + logPath(source) + " ==> " + logPath(dest));
- if (symlink)
- FILE.symlink(source, dest);
- else
- FILE.copyTree(source, dest);
- }
- else
- warn("Cannot find: " + logPath(source));
- }
- function toIdentifier(/*String*/ aString)
- {
- var identifier = "",
- count = aString.length,
- capitalize = NO,
- firstRegex = new RegExp("^[a-zA-Z_$]"),
- regex = new RegExp("^[a-zA-Z_$0-9]");
- for (var index = 0; index < count; ++index)
- {
- var character = aString.charAt(index);
- if ((index === 0) && firstRegex.test(character) || regex.test(character))
- {
- if (capitalize)
- identifier += character.toUpperCase();
- else
- identifier += character;
- capitalize = NO;
- }
- else
- capitalize = YES;
- }
- return identifier;
- }
- function listTemplates()
- {
- FILE.list(templatesDirectory).forEach(function(templateName)
- {
- stream.print(templateName);
- });
- }
- function listFrameworks()
- {
- stream.print("Frameworks:");
- OBJJ.objj_frameworks.forEach(function(frameworksDirectory)
- {
- stream.print(" " + frameworksDirectory);
- FILE.list(frameworksDirectory).forEach(function(templateName)
- {
- stream.print(" + " + templateName);
- });
- });
- stream.print("Frameworks (Debug):");
- OBJJ.objj_debug_frameworks.forEach(function(frameworksDirectory)
- {
- stream.print(" " + frameworksDirectory);
- FILE.list(frameworksDirectory).forEach(function(frameworkName)
- {
- stream.print(" + " + frameworkName);
- });
- });
- }
- function executePostInstallScript(/*String*/ destinationProject)
- {
- var path = FILE.join(destinationProject, "postinstall");
- if (FILE.exists(path))
- {
- stream.print(colorize("Executing postinstall script...", "cyan"));
- OS.system(["/bin/sh", path, destinationProject]); // Use sh in case it isn't marked executable
- FILE.remove(path);
- }
- }
- function colorize(message, color)
- {
- return "\0" + color + "(" + message + "\0)";
- }
- function logPath(path)
- {
- return colorize(path, "cyan");
- }
- function warn(message)
- {
- stream.print(colorize("Warning: ", "yellow") + message);
- }
- function fail(message)
- {
- stream.print(colorize(message, "red"));
- OS.exit(1);
- }