Class: SC::Tools
- Defined in:
- lib/sproutcore/tools.rb,
lib/sproutcore/tools/gen.rb,
lib/sproutcore/tools/init.rb,
lib/sproutcore/tools/build.rb,
lib/sproutcore/tools/server.rb,
lib/sproutcore/tools/manifest.rb,
lib/sproutcore/tools/build_number.rb
Overview
Generates components for SproutCore. The generator allows the user to quickly set up a SproutCore framework using any of the built in templates such as the project itself, apps, models, views, controllers and more
The template files will be copied to their target location and also be parsed through the Erubis templating system. Template file paths can contain instance variables in the form of class_name which in turn would be the value of class_name once generated.
To develop a new generator, you can add it to the sproutcore/gen/ directory with the following file structure:
gen/
<generator_name>/ - singular directory name of the generator
Buildfile - contains all config options and build tasks
README - prints when generator is done
templates/ - contains all the files you want to generate
USAGE - prints when user gives uses --help option
Defined Under Namespace
Classes: FatalException
Constant Summary collapse
- MANIFEST_OPTIONS =
Standard manifest options. Used by build tool as well.
{ :languages => :optional, :symlink => false, :buildroot => :optional, :stageroot => :optional, :format => :optional, :output => :output, :all => false, ['--include-required', '-r'] => false }
Class Method Summary collapse
-
.start(args = ARGV) ⇒ Object
Fix start so that it treats command-name like command_name.
Instance Method Summary collapse
- #build(*targets) ⇒ Object
-
#build_manifests(*targets) ⇒ Object
Core method to process command line options and then build a manifest.
- #build_number(*targets) ⇒ Object
-
#debug(description) ⇒ Object
Helper method.
-
#fatal!(description) ⇒ Object
Helper method.
-
#find_languages(*targets) ⇒ Object
Discovers the languages requested by the user for a build.
-
#find_targets(*targets) ⇒ Object
Find one or more targets with the passed target names in the current project.
- #gen(*arguments) ⇒ Object
-
#info(description) ⇒ Object
Helper method.
- #init(project_name, app_name = nil) ⇒ Object
-
#initialize(options, *args) ⇒ Tools
constructor
A new instance of Tools.
-
#invoke(*args) ⇒ Object
This is the core entry method used to run every tool.
-
#log_file(path) ⇒ Object
Logs the contents of the passed file path to the logger.
- #manifest(*targets) ⇒ Object
-
#options ⇒ Object
Make the options hash a HashStruct so that we can access each variable as a method.
-
#prepare_build_numbers! ⇒ Object
Configure the current build numbers.
-
#prepare_logger! ⇒ Object
Configure the expected log level and log target.
-
#prepare_mode!(preferred_mode = 'production') ⇒ Object
Configure the current build mode.
-
#project ⇒ Object
The current project.
-
#project=(a_project) ⇒ Object
Set the current project.
-
#requires_project! ⇒ Object
Attempts to discover the current project.
-
#requires_target!(*targets) ⇒ Object
Requires exactly one target.
-
#requires_targets!(*target_names) ⇒ Object
Wraps around find_targets but raises an exception if no target is specified.
- #server ⇒ Object
- #show_help(generator_name = nil, generator = nil) ⇒ Object
-
#warn(description) ⇒ Object
Log this when you need to issue a warning.
Methods inherited from Thor
[], default_task, desc, group, group_name, #help, install_task, invoke, map, maxima, method_options, opts, package_task, spec_task, subclass_files, subclasses, tasks
Constructor Details
#initialize(options, *args) ⇒ Tools
Returns a new instance of Tools.
77 78 79 |
# File 'lib/sproutcore/tools.rb', line 77 def initialize(, *args) super end |
Class Method Details
.start(args = ARGV) ⇒ Object
Fix start so that it treats command-name like command_name
303 304 305 306 307 308 309 310 311 312 313 314 315 |
# File 'lib/sproutcore/tools.rb', line 303 def self.start(args = ARGV) # manually check for verbose in case we don't get far enough in regular # processing to actually set the verbose mode. is_verbose = %w(-v -V --verbose --very-verbose).any? { |x| args.include?(x) } begin super(args) rescue Exception => e SC.logger.fatal(e) if is_verbose && !e.kind_of?(FatalException) SC.logger.fatal("BACKTRACE:\n#{e.backtrace.join("\n")}\n") end end end |
Instance Method Details
#build(*targets) ⇒ Object
17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 |
# File 'lib/sproutcore/tools/build.rb', line 17 def build(*targets) # Copy some key props to the env SC.env.build_prefix = .buildroot if .buildroot SC.env.stating_prefix = .stageroot if .stageroot SC.env.use_symlink = .symlink SC.env.clean = .clean # Get entries option entry_filters = nil if [:entries] entry_filters = [:entries].split(',') end # Get the manifests to build manifests = build_manifests(*targets) # First clean all manifests # Do this before building so we don't accidentally erase already build # nested targets. if SC.env.clean manifests.each do |manifest| build_root = manifest.target.build_root info "Cleaning #{build_root}" FileUtils.rm_r(build_root) if File.directory?(build_root) staging_root = manifest.target.staging_root info "Cleaning #{staging_root}" FileUtils.rm_r(staging_root) if File.directory?(staging_root) end end # Now build entries for each manifest... manifests.each do |manifest| # get entries. If "entries" option was specified, use to filter # filename. Must match end of filename. entries = manifest.entries if entry_filters entries = entries.select do |entry| is_allowed = false entry_filters.each do |filter| is_allowed = entry.filename =~ /#{filter}$/ break if is_allowed end is_allowed end end # if there are entries to build, log and build if entries.size > 0 info "Building entries for #{manifest.target.target_name}:#{manifest.language}..." entries.each do |entry| info " #{entry.filename} -> #{entry.build_path}" entry.build! end end end end |
#build_manifests(*targets) ⇒ Object
Core method to process command line options and then build a manifest. Shared by sc-manifest and sc-build commands.
263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 |
# File 'lib/sproutcore/tools.rb', line 263 def build_manifests(*targets) requires_project! # get project targets = find_targets(*targets) # get targets languages = find_languages(*targets) # get languages # log output SC.logger.info "Building targets: #{targets.map { |t| t.target_name } * ","}" SC.logger.info "Building languages: #{ languages * "," }" # Now fetch the manifests to build. One per target/language manifests = targets.map do |target| languages.map { |l| target.manifest_for :language => l } end manifests.flatten! # Build'em manifests.each do |manifest| SC.logger.info "Building manifest for: #{manifest.target.target_name}:#{manifest.language}" manifest.build! end return manifests end |
#build_number(*targets) ⇒ Object
17 18 19 20 |
# File 'lib/sproutcore/tools/build_number.rb', line 17 def build_number(*targets) target = requires_target!(*targets) $stdout << target.prepare!.build_number end |
#debug(description) ⇒ Object
Helper method. Call this when you want to log a debug message.
53 54 55 |
# File 'lib/sproutcore/tools.rb', line 53 def debug(description) SC.logger.debug(description) end |
#fatal!(description) ⇒ Object
Helper method. Call this when an acception occurs that is fatal due to a problem with the user.
42 43 44 |
# File 'lib/sproutcore/tools.rb', line 42 def fatal!(description) raise FatalException, description end |
#find_languages(*targets) ⇒ Object
Discovers the languages requested by the user for a build. Uses the --languages command line option or disovers in targets.
250 251 252 253 254 255 256 257 258 259 |
# File 'lib/sproutcore/tools.rb', line 250 def find_languages(*targets) # Use passed languages. If none are specified, merge installed # languages for all app targets. if (languages = .languages).nil? languages = targets.map { |t| t.installed_languages } else languages = languages.split(':').map { |l| l.to_sym } end languages.flatten.uniq.compact end |
#find_targets(*targets) ⇒ Object
Find one or more targets with the passed target names in the current project. Requires a project to function.
177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 |
# File 'lib/sproutcore/tools.rb', line 177 def find_targets(*targets) debug "finding targets with names: '#{targets * "','"}'" requires_project! # Filter out any empty target names. Sometimes this happens when # processing arguments. targets.reject! { |x| x.nil? || x.size == 0 } # If targets are specified, find the targets project or parents... if targets.size > 0 targets = targets.map do |target_name| begin ret = project.target_for(target_name) rescue Exception => e SC.logger.fatal("Exception when searching for target #{target_name}. Perhaps your Buildfile is configured wrong?") raise e end if ret.nil? fatal! "No target named #{target_name} could be found in project" else debug "Found target '#{target_name}' at PROJECT:#{ret.source_root.sub(/^#{project.project_root}\//,'')}" end ret end # IF no targets are specified, then just get all targets in project. # If --all option was specified, include those that do not autobuild else targets = project.targets.values unless .all? targets.reject! { |t| !t.config.autobuild? } end end # If include required was specified, merge in all required bundles as # well. if ['include-required'] targets.each do |target| targets += target. :theme => true, :debug => target.config.load_debug, :tests => target.config.load_tests end targets = targets.flatten.uniq.compact end return targets end |
#gen(*arguments) ⇒ Object
58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 |
# File 'lib/sproutcore/tools/gen.rb', line 58 def gen(*arguments) return show_help if arguments.empty? # backwards compatibility case: client is a synonym for 'app' name = arguments[0]=='client' ? 'app' : arguments[0] # Load generator generator_project = self.project || SC.builtin_project generator = generator_project.generator_for name, :arguments => arguments, :filename => [:filename], :target_name => [:target], :dry_run => ['dry-run'], :force => [:force] # if no generator could be found, or if we just asked to show help, # just return the help... return show_help(name, generator) if generator.nil? || [:help] begin # Prepare generator and then log some debug info generator.prepare! info "Loading generator Buildfile at: #{generator.buildfile.loaded_paths.last}" debug "\nSETTINGS" generator.each { |k,v| debug("#{k}: #{v}") } # Now, run the generator generator.build! rescue Exception => warn "For specific help on how to use this generator, type: sc-gen #{name} --help" fatal! .to_s end SC.logger << "\n" generator.log_readme return 0 end |
#info(description) ⇒ Object
Helper method. Call this when you want to log an info message. Logs to the standard logger.
48 49 50 |
# File 'lib/sproutcore/tools.rb', line 48 def info(description) SC.logger.info(description) end |
#init(project_name, app_name = nil) ⇒ Object
14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
# File 'lib/sproutcore/tools/init.rb', line 14 def init(project_name, app_name=nil) # Generate the project project_gen = SC.builtin_project.generator_for 'project', :arguments => ['project', project_name], :dry_run => ['dry-run'], :force => [:force] project_gen.prepare!.build! # Next, get the project root & app name project_root = project_gen.build_root / project_gen.filename app_name = project_gen.filename if app_name.nil? # And get the app generator and run it project = SC::Project.load project_root, :parent => SC.builtin_project generator = project.generator_for 'app', :arguments => ['app', app_name], :dry_run => ['dry-run'], :force => [:force] generator.prepare!.build! project_gen.log_file(project_gen.source_root / 'INIT') return 0 end |
#invoke(*args) ⇒ Object
This is the core entry method used to run every tool. Extend this method with any standard preprocessing you want all tools to do before they do their specific thing.
84 85 86 87 88 89 |
# File 'lib/sproutcore/tools.rb', line 84 def invoke(*args) prepare_logger! prepare_mode! prepare_build_numbers! super end |
#log_file(path) ⇒ Object
Logs the contents of the passed file path to the logger
289 290 291 292 293 294 295 296 |
# File 'lib/sproutcore/tools.rb', line 289 def log_file(path) if !File.exists?(path) warn "Could not display #{File.basename(path)} at #{File.dirname(path)} because it does not exist." end file_text = File.read(path) SC.logger << file_text SC.logger << "\n" end |
#manifest(*targets) ⇒ Object
27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 |
# File 'lib/sproutcore/tools/manifest.rb', line 27 def manifest(*targets) # Copy some key props to the env SC.env.build_prefix = .buildroot if .buildroot SC.env.staging_prefix = .stageroot if .stageroot SC.env.use_symlink = .symlink # Verify format format = (.format || 'yaml').to_s.downcase.to_sym if ![:yaml, :json].include?(format) raise "Format must be yaml or json" end # Get allowed keys only_keys = nil if [:only] only_keys = ([:only] || '').to_s.split(',') only_keys.map! { |k| k.to_sym } only_keys = nil if only_keys.size == 0 end except_keys = nil if [:except] except_keys = ([:except] || '').to_s.split(',') except_keys.map! { |k| k.to_sym } except_keys = nil if except_keys.size == 0 end # call core method to actually build the manifests... manifests = build_manifests(*targets) # now convert them to hashes... manifests.map! do |manifest| manifest.to_hash :hidden => .hidden, :only => only_keys, :except => except_keys end # Serialize'em case format when :yaml output = ["# SproutCore Build Manifest v1.0", manifests.to_yaml].join("\n") when :json output = mainfests.to_json end # output ... if .output file = File.open(.output, 'w') file.write(output) file.close else $stdout << output end end |
#options ⇒ Object
Make the options hash a HashStruct so that we can access each variable as a method
93 |
# File 'lib/sproutcore/tools.rb', line 93 def ; ||= HashStruct.new(super); end |
#prepare_build_numbers! ⇒ Object
Configure the current build numbers. Handles the --build option.
110 111 112 113 114 115 116 117 118 119 120 121 122 123 |
# File 'lib/sproutcore/tools.rb', line 110 def prepare_build_numbers! return if (numbers = .build).nil? numbers = numbers.split(',').map { |n| n.split(':') } if numbers.size==1 && numbers.first.size==1 SC.env.build_number = numbers.first.first else hash = {} numbers.each do |pair| key = pair[0] key = "/#{key}" if !(key =~ /^\//) hash[key.to_sym] = pair[1] end end end |
#prepare_logger! ⇒ Object
Configure the expected log level and log target. Handles the --verbose, --very-verbose and --logfile options
97 98 99 100 |
# File 'lib/sproutcore/tools.rb', line 97 def prepare_logger! SC.env.log_level = ['very-verbose'] ? :debug : (.verbose ? :info : :warn) SC.env.logfile = File.(.logfile) if .logfile end |
#prepare_mode!(preferred_mode = 'production') ⇒ Object
Configure the current build mode. Handles the --mode and --environment options. (--environment is provided for backwards compatibility)
104 105 106 107 |
# File 'lib/sproutcore/tools.rb', line 104 def prepare_mode!(preferred_mode = 'production') build_mode = (.mode || .environment || preferred_mode).to_s.downcase.to_sym SC.build_mode = build_mode end |
#project ⇒ Object
The current project. This is discovered based on the passed --project option or based on the current working directory. If no project can be found, this method will always return null.
137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 |
# File 'lib/sproutcore/tools.rb', line 137 def project return @project if @discovered_project # cache - @project may be nil @discovered_project = true ret = nil project_path = .project || .library # if no project_path is named explicitly, attempt to autodiscover from # working dir. If none is found, just set project to nil if project_path.nil? debug "No project path specified. Searching for projects in #{Dir.pwd}" ret = SC::Project.load_nearest_project Dir.pwd, :parent => SC.builtin_project # if project path is specified, look there. If no project is found # die with a fatal exception. else debug "Project path specified at #{project_path}" ret = SC::Project.load File.(project_path), :parent => SC.builtin_project if ret.nil? fatal! "Could not load project at #{project_path}" end end info "Loaded project at: #{ret.project_root}" unless ret.nil? @project = ret end |
#project=(a_project) ⇒ Object
Set the current project. This is used mostly for unit testing.
130 131 132 |
# File 'lib/sproutcore/tools.rb', line 130 def project=(a_project) @project = a_project end |
#requires_project! ⇒ Object
Attempts to discover the current project. If no project can be found throws a fatal exception. Use this method at the top of your tool method if you require a project to run.
167 168 169 170 171 172 173 |
# File 'lib/sproutcore/tools.rb', line 167 def requires_project! ret = project if ret.nil? fatal!("You do not appear to be inside of a project. Try changing to your project directory or make sure your project as a Buildfile or sc-config") end return ret end |
#requires_target!(*targets) ⇒ Object
Requires exactly one target.
244 245 246 |
# File 'lib/sproutcore/tools.rb', line 244 def requires_target!(*targets) requires_targets!(*targets).first end |
#requires_targets!(*target_names) ⇒ Object
Wraps around find_targets but raises an exception if no target is specified.
230 231 232 233 234 235 236 237 238 239 240 241 |
# File 'lib/sproutcore/tools.rb', line 230 def requires_targets!(*target_names) if target_names.size == 0 fatal! "You must specify a target with this command" end targets = find_targets(*target_names) if targets.size == 0 fatal! "No targets matching #{target_names * ","} were found." end targets end |
#server ⇒ Object
19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 |
# File 'lib/sproutcore/tools/server.rb', line 19 def server prepare_mode!('debug') # set mode again, using debug as default SC.env.build_prefix = .buildroot if .buildroot SC.env.staging_prefix = .stageroot if .stageroot # get project and start service. project = requires_project! # start shell if passed if .irb require 'irb' require 'irb/completion' if File.exists? ".irbrc" ENV['IRBRC'] = ".irbrc" end SC.project = project SC.logger << "SproutCore v#{SC::VERSION} Interactive Shell\n" SC.logger << "SC.project = #{project.project_root}\n" ARGV.clear # do not pass onto IRB IRB.start else SC::Rack::Service.start(.merge(:project => project)) end end |
#show_help(generator_name = nil, generator = nil) ⇒ Object
31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 |
# File 'lib/sproutcore/tools/gen.rb', line 31 def show_help(generator_name=nil, generator=nil) if generator_name if generator.nil? warn("There is no #{generator_name} generator") else generator.log_usage end else SC.logger << "Available generators:\n" SC::Generator.installed_generators_for(project).each do |name| SC.logger << " #{name}\n" end SC.logger << "Type sc-gen GENERATOR --help for specific usage\n\n" end return 0 end |
#warn(description) ⇒ Object
Log this when you need to issue a warning.
58 59 60 |
# File 'lib/sproutcore/tools.rb', line 58 def warn(description) SC.logger.warn(description) end |