Permalink
Browse files

Basic workflow for building projects is now in place. Rake tasks are …

…used at key points in the process, allowing you to override them if needed.
  • Loading branch information...
1 parent 6aa24d4 commit bc9e812c8927d6f9ac999b77ad15992a900de3db Charles Jolley committed Jan 10, 2009
View
@@ -1,3 +1,6 @@
+# Import all build tasks
+import *Dir.glob(File.join(File.dirname(__FILE__), 'buildtasks', '**', '*.rake'))
+
config :all,
# REQUIRED CONFIGS
@@ -17,5 +20,25 @@ config :all,
# Allows the target to have other targets nested inside of it. Override
# this in your target Buildfile to disable nesting.
- :allow_nested_targets => true
-
+ :allow_nested_targets => true,
+
+ :preferred_language => :en
+
+namespace :manifest do
+
+ # This task is invoked by the build system whenever it needs to generate
+ # a manifest. If you supply a manifest file to a build process, the file
+ # will be used directly and this task will not be invoked.
+ #
+ # The default version of this tool will execute the "sc-manifest build" tool
+ # and load the results into the manifest. (Actually it will invoke the tool
+ # internally, but the effect is the same)
+ #
+ # You can override this task to call out to your own tool to process the
+ # manifest.
+ #
+ task :prepare do
+ SC::Tools::Manifest.build(MANIFEST)
+ end
+
+end
View
@@ -0,0 +1,53 @@
+# ===========================================================================
+# SC::ManifestEntry Buildtasks
+# copyright 2008, Sprout Systems, Inc. and Apple, Inc. all rights reserved
+# ===========================================================================
+
+# Tasks invoked while building ManifestEntry objects. You can override these
+# tasks in your buildfiles.
+namespace :entry do
+
+ # Invoked whenever a new entry is added. Gives you a chance to fill in any
+ # standard properties. The default implementation ensures that the entry
+ # has at least a source_path, build_path, staging_path, url and build_task
+ #
+ # With this task in place, you can build an entry by simply providing a
+ # filename and, optionally a source_path or source_entries.
+ task :prepare do
+ filename = ENTRY.filename
+ raise "All entries must have a filename!" if filename.nil?
+
+ # If this is a composite entry, then the source_paths array should
+ # contain the staging_path from the source_entries. The source_path
+ # is simply the first source_paths.
+ if ENTRY.composite?
+ ENTRY.source_entries ||= []
+ ENTRY.source_paths ||= ENTRY.source_entries.map { |e| e.staging_path }
+ ENTRY.source_path ||= ENTRY.source_paths.first
+
+ # Otherwise, the source_path is where we will pull from and source_paths
+ # is simply the source_path in an array.
+ else
+ ENTRY.source_path ||= File.join(MANIFEST.source_root, filename)
+ ENTRY.source_paths ||= [ENTRY.source_path]
+ end
+
+ # Construct some easier paths if needed
+ ENTRY.build_path ||= File.join(MANIFEST.build_root, filename)
+ ENTRY.url ||= [MANIFEST.url_root, filename].join('/')
+
+ # Fill in a default build task
+ ENTRY.build_task ||= 'build:copy'
+
+ # If the build_task is build:copy, make the staging path equal the
+ # source_root. This is an optimization that will avoid unnecessary
+ # copying. All other build_tasks we build a staging path from the root.
+ if ENTRY.build_task.to_s == 'build:copy'
+ ENTRY.staging_path ||= ENTRY.source_path
+ else
+ ENTRY.staging_path ||= File.join(MANIFEST.staging_root, filename)
+ end
+ end
+
+end
+
View
@@ -0,0 +1,37 @@
+# ===========================================================================
+# SC::Manifest Buildtasks
+# copyright 2008, Sprout Systems, Inc. and Apple, Inc. all rights reserved
+# ===========================================================================
+
+# Tasks invoked while building Manifest objects. You can override these
+# tasks in your buildfiles.
+namespace :manifest do
+
+ # Invoked just before a manifest object is built to setup any standard
+ # properties on the manifest. The default configures a build_root,
+ # source_root, staging_root, url_root, index_root and more.
+ task :prepare do
+ require 'tempfile'
+
+ # make sure a language was set
+ MANIFEST.language ||= :en
+
+ # build_root is target.build_root + language + build_number
+ MANIFEST.build_root = File.join(TARGET.build_root,
+ MANIFEST.language.to_s, TARGET.build_number.to_s)
+
+ # staging_root is target.staging_root + language + build_number
+ MANIFEST.staging_root = File.join(TARGET.staging_root,
+ MANIFEST.language.to_s, TARGET.build_number.to_s)
+
+ # url_root
+ MANIFEST.url_root =
+ [TARGET.url_root, MANIFEST.language, TARGET.build_number].join('/')
+
+ # index_root
+ MANIFEST.index_root =
+ [TARGET.index_root, MANIFEST.language, TARGET.build_number].join('/')
+
+ end
+
+end
View
@@ -0,0 +1,53 @@
+# ===========================================================================
+# SC::Target Buildtasks
+# copyright 2008, Sprout Systems, Inc. and Apple, Inc. all rights reserved
+# ===========================================================================
+
+# Tasks invoked while building Target objects. You can override these methods
+# in your buildfiles.
+namespace :target do
+
+ # Invoked whenever a new target is created to prepare standard properties
+ # needed on the build system. Extend this task to add other standard
+ # properties
+ task :prepare do
+
+ # use url_root config or merge url_prefix + target_name
+ TARGET.url_root = CONFIG.url_root ||
+ ['/', CONFIG.url_prefix, TARGET.target_name].join('')
+
+ # use index_root config or merge index_prefix + target_name
+ TARGET.index_root = CONFIG.index_root ||
+ ['/', CONFIG.index_prefix, TARGET.target_name].join('')
+
+ TARGET.build_root = CONFIG.build_root ||
+ File.join(PROJECT.project_root.to_s,
+ CONFIG.public_prefix.to_s, CONFIG.url_prefix.to_s,
+ TARGET.target_name.to_s)
+
+ TARGET.staging_root = File.join(PROJECT.project_root.to_s,
+ (PROJECT.config.staging_prefix || 'tmp').to_s, 'staging',
+ TARGET.target_name.to_s)
+
+ end
+
+ # Invoked by the build system to select the build number for a target. The
+ # default version will respect the build_number config or looks for a
+ # build_numbers hash in the config. If no config is found it will compute
+ # the build number using an MD5 hash of the target contents.
+ task :build_number do
+
+ # If config specifies a build number specifically for this target, use it
+ build_number = CONFIG.build_number
+
+ # Otherwise, look for a global build_numbers hash and try that
+ if build_number.nil? && (build_numbers = CONFIG.build_numbers)
+ build_number = build_numbers[TARGET.target_name.to_s] || build_numbers[TARGET.target_name.to_sym]
+ end
+
+ # Otherwise, actually compute a build number. This may be expensive
+ build_number = TARGET.compute_build_number
+ TARGET.build_number = build_number
+ end
+
+end
@@ -31,11 +31,11 @@ class Buildfile
#
# Determines if this directory has a buildfile or not...
- def self.has_buildfile?(dir_path, buildfile_names)
+ def self.has_buildfile?(dir_path, buildfile_names=nil)
buildfile_names ||= (SC.env.buildfile_names || BUILDFILE_NAMES)
buildfile_names.each do |path|
path = File.join(dir_path, path)
- return true if File.exist?(path) && !File.directory(path)
+ return true if File.exist?(path) && !File.directory?(path)
end
return false
end
View
@@ -14,30 +14,73 @@ def initialize(target, opts)
super(opts)
@target = target
@entries = []
- @is_prepared = NO
end
- def prepared?; @is_prepared; end
- def prepared!; @is_prepared = YES; end
+ # Invoked just before a manifest is built. If you load a manifest file
+ # this method will not be invoked.
+ # === Returns
+ # self
+ def prepare!
+ if !@is_prepared
+ @is_prepared = true
+ if target.buildfile.task_defined? 'manifest:prepare'
+ target.buildfile.execute_task 'manifest:prepare',
+ :manifest => self,
+ :target => self.target,
+ :config => self.target.config,
+ :project => self.target.project
+ end
+ end
+ return self
+ end
+ # Builds the manifest. This will prepare the manifest and then invoke
+ # the manifest:build task if defined.
+ def build!
+ prepare!
+ if target.buildfile.task_defined? 'manifest:build'
+ target.buildfile.execute_task 'manifest:build',
+ :manifest => self,
+ :target => self.target,
+ :config => self.target.config,
+ :project => self.target.project
+ end
+ return self
+ end
+
+ # Resets the manifest entries. this is called before a build is
+ # performed. This will reset only the entries, none of the other props.
+ #
+ # === Returns
+ # Manifest (self)
+ #
+ def reset_entries!
+ @entries = []
+ return self
+ end
+
+ # Returns the manifest as a hash that can be serialized to json or yaml
def to_hash
ret = super
ret[:entries] = entries.map { |e| e.to_hash }
return ret
end
- # Reset the manifest. This will clear out the existing manifest and set
- # it to need another build. The next time you call build!, the manifest
- # will be rebuilt.
+ # Loads a hash into the manifest, replacing whatever contents are
+ # already here.
#
- # ==== Returns
- # self
+ # === Params
+ # hash:: the hash loaded from disk
#
- def reset!
- @needs_build = true
- @entries = []
- keys.each { |k| self.delete(k) }
- self[:language] = @language
+ # === Returns
+ # Manifest (self)
+ #
+ def load_hash!(hash)
+ merge!(hash)
+ entry_hashes = self.delete(:entries) || []
+ @entries = entry_hashes.map do |opts|
+ ManifestEntry.new(self, opts)
+ end
return self
end
@@ -50,9 +93,9 @@ def reset!
# ==== Returns
# the new manifest entry
#
- def add_entry(opts = {})
- opts[:manifest] = self
- @entries << (ret = ManifestEntry.new(opts))
+ def add_entry(filename, opts = {})
+ opts[:filename] = filename
+ @entries << (ret = ManifestEntry.new(self, opts)).prepare!
return ret
end
Oops, something went wrong.

0 comments on commit bc9e812

Please sign in to comment.