New project creation implemented using manifests and installation strategies.
This commit is contained in:
parent
0ac537a81b
commit
91e081cd50
5
frameworks/blueprint/templates/project/manifest.rb
Normal file
5
frameworks/blueprint/templates/project/manifest.rb
Normal file
@ -0,0 +1,5 @@
|
||||
stylesheet 'screen.sass'
|
||||
stylesheet 'print.sass'
|
||||
stylesheet 'ie.sass'
|
||||
|
||||
image 'grid.png'
|
3
frameworks/compass/templates/project/manifest.rb
Normal file
3
frameworks/compass/templates/project/manifest.rb
Normal file
@ -0,0 +1,3 @@
|
||||
stylesheet 'screen.sass'
|
||||
stylesheet 'print.sass'
|
||||
stylesheet 'ie.sass'
|
1
frameworks/yui/templates/project/manifest.rb
Normal file
1
frameworks/yui/templates/project/manifest.rb
Normal file
@ -0,0 +1 @@
|
||||
stylesheet 'screen.sass'
|
@ -1,38 +1,30 @@
|
||||
require 'fileutils'
|
||||
require File.join(File.dirname(__FILE__), 'base')
|
||||
require File.join(File.dirname(__FILE__), 'update_project')
|
||||
require File.join(Compass.lib_directory, 'compass', 'installers')
|
||||
|
||||
module Compass
|
||||
module Commands
|
||||
class CreateProject < ProjectBase
|
||||
|
||||
|
||||
include Compass::Installers
|
||||
|
||||
def initialize(working_directory, options)
|
||||
super(working_directory, options)
|
||||
end
|
||||
|
||||
# all commands must implement perform
|
||||
def perform
|
||||
begin
|
||||
directory nil, options
|
||||
rescue Compass::Exec::DirectoryExistsError
|
||||
msg = "Project directory already exists. Run with -u to update or --force to force creation."
|
||||
raise ::Compass::Exec::DirectoryExistsError.new(msg)
|
||||
end
|
||||
src_dir = options[:src_dir] || "src"
|
||||
css_dir = options[:css_dir] || "stylesheets"
|
||||
directory src_dir, options.merge(:force => true)
|
||||
directory css_dir, options.merge(:force => true)
|
||||
framework_templates.each do |t|
|
||||
template "project/#{t}", "#{src_dir}/#{t}", options
|
||||
end
|
||||
installer.run
|
||||
UpdateProject.new(working_directory, options).perform
|
||||
end
|
||||
|
||||
def framework_templates
|
||||
framework_project_dir = File.join(templates_directory, "project")
|
||||
Dir.chdir(framework_project_dir) do
|
||||
Dir.glob("*")
|
||||
end
|
||||
def installer
|
||||
StandAloneInstaller.new(project_template_directory, project_directory, options)
|
||||
end
|
||||
|
||||
def project_template_directory
|
||||
File.join(framework.templates_directory, "project")
|
||||
end
|
||||
|
||||
def skip_project_directory_assertion?
|
||||
|
16
lib/compass/installers.rb
Normal file
16
lib/compass/installers.rb
Normal file
@ -0,0 +1,16 @@
|
||||
module Compass
|
||||
module Installers
|
||||
|
||||
class InstallationError < Compass::Error
|
||||
end
|
||||
|
||||
class DirectoryExistsError < InstallationError
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
require File.join(File.dirname(__FILE__), 'installers', 'manifest')
|
||||
require File.join(File.dirname(__FILE__), 'installers', 'base')
|
||||
require File.join(File.dirname(__FILE__), 'installers', 'stand_alone')
|
||||
|
179
lib/compass/installers/base.rb
Normal file
179
lib/compass/installers/base.rb
Normal file
@ -0,0 +1,179 @@
|
||||
module Compass
|
||||
module Installers
|
||||
|
||||
class Base
|
||||
attr_accessor :template_path, :target_path, :working_path
|
||||
attr_accessor :options
|
||||
attr_accessor :manifest
|
||||
attr_accessor :logger
|
||||
attr_accessor :css_dir, :sass_dir, :images_dir, :javascripts_dir
|
||||
|
||||
def initialize(template_path, target_path, options = {})
|
||||
@template_path = template_path
|
||||
@target_path = target_path
|
||||
@working_path = Dir.getwd
|
||||
@options = options
|
||||
@manifest = Manifest.new(manifest_file)
|
||||
configure_option_with_default :logger
|
||||
end
|
||||
|
||||
def manifest_file
|
||||
@manifest_file ||= File.join(template_path, "manifest.rb")
|
||||
end
|
||||
|
||||
# Runs the installer.
|
||||
# Every installer must conform to the installation strategy of configure, prepare, install, and then finalize.
|
||||
# A default implementation is provided for each step.
|
||||
def run
|
||||
configure
|
||||
prepare
|
||||
install
|
||||
finalize
|
||||
end
|
||||
|
||||
# The default configure method -- it sets up directories from the options
|
||||
# and corresponding default_* methods for those not found in the options hash.
|
||||
# It can be overridden it or augmented for reading config files,
|
||||
# prompting the user for more information, etc.
|
||||
def configure
|
||||
[:css_dir, :sass_dir, :images_dir, :javascripts_dir].each do |opt|
|
||||
configure_option_with_default opt
|
||||
end
|
||||
end
|
||||
|
||||
# The default prepare method -- it is a no-op.
|
||||
# Generally you would create required directories, etc.
|
||||
def prepare
|
||||
end
|
||||
|
||||
def configure_option_with_default(opt)
|
||||
value = options[opt]
|
||||
value ||= begin
|
||||
default_method = "default_#{opt}".to_sym
|
||||
send(default_method) if respond_to?(default_method)
|
||||
end
|
||||
send("#{opt}=", value)
|
||||
end
|
||||
|
||||
# The default install method. Calls install_<type> methods in the order specified by the manifest.
|
||||
def install
|
||||
manifest.each do |entry|
|
||||
send("install_#{entry.type}", entry.from, entry.options)
|
||||
end
|
||||
end
|
||||
|
||||
# The default finalize method -- it is a no-op.
|
||||
# This could print out a message or something.
|
||||
def finalize
|
||||
end
|
||||
|
||||
|
||||
def install_stylesheet(from, options)
|
||||
to = options[:to] || from
|
||||
copy from, "#{sass_dir}/#{to}"
|
||||
end
|
||||
|
||||
def install_image(from, options)
|
||||
to = options[:to] || from
|
||||
copy from, "#{images_dir}/#{to}"
|
||||
end
|
||||
|
||||
def install_script(from, options)
|
||||
to = options[:to] || from
|
||||
copy from, "#{javascripts_dir}/#{to}"
|
||||
end
|
||||
|
||||
def install_file(from, options)
|
||||
to = options[:to] || from
|
||||
copy from, to
|
||||
end
|
||||
|
||||
def default_logger
|
||||
Compass::Logger.new
|
||||
end
|
||||
|
||||
# returns an absolute path given a path relative to the current installation target.
|
||||
# Paths can use unix style "/" and will be corrected for the current platform.
|
||||
def targetize(path)
|
||||
File.join(target_path, separate(path))
|
||||
end
|
||||
|
||||
# returns an absolute path given a path relative to the current template.
|
||||
# Paths can use unix style "/" and will be corrected for the current platform.
|
||||
def templatize(path)
|
||||
File.join(template_path, separate(path))
|
||||
end
|
||||
|
||||
# Write paths like we're on unix and then fix it
|
||||
def separate(path)
|
||||
path.gsub(%r{/}, File::SEPARATOR)
|
||||
end
|
||||
|
||||
# copy/process a template in the compass template directory to the project directory.
|
||||
def copy(from, to, options = nil)
|
||||
options ||= self.options
|
||||
from = templatize(from)
|
||||
to = targetize(to)
|
||||
if File.exists?(to) && !options[:force]
|
||||
#TODO: Detect differences & provide an overwrite prompt
|
||||
msg = "#{basename(to)} already exists."
|
||||
raise InstallationError.new(msg)
|
||||
elsif File.exists?(to)
|
||||
logger.record :overwrite, basename(to)
|
||||
FileUtils.rm to unless options[:dry_run]
|
||||
FileUtils.cp from, to unless options[:dry_run]
|
||||
else
|
||||
logger.record :create, basename(to)
|
||||
FileUtils.cp from, to unless options[:dry_run]
|
||||
end
|
||||
end
|
||||
|
||||
# create a directory and all the directories necessary to reach it.
|
||||
def directory(dir, options = nil)
|
||||
options ||= self.options
|
||||
dir = targetize(dir)
|
||||
if File.exists?(dir) && File.directory?(dir)
|
||||
logger.record :exists, basename(dir)
|
||||
elsif File.exists?(dir)
|
||||
msg = "#{basename(dir)} already exists and is not a directory."
|
||||
raise InstallationError.new(msg)
|
||||
else
|
||||
logger.record :directory, basename(dir)
|
||||
FileUtils.mkdir_p(dir) unless options[:dry_run]
|
||||
end
|
||||
end
|
||||
|
||||
def write_file(file_name, contents, options = nil)
|
||||
options ||= self.options
|
||||
file_name = targetize(file_name)
|
||||
if File.exists?(file_name) && !options[:force]
|
||||
msg = "File #{basename(file_name)} already exists. Run with --force to force creation."
|
||||
raise InstallationError.new(msg)
|
||||
end
|
||||
if File.exists?(file_name)
|
||||
logger.record :overwrite, basename(file_name)
|
||||
else
|
||||
logger.record :create, basename(file_name)
|
||||
end
|
||||
open(file_name,'w') do |file|
|
||||
file.write(contents)
|
||||
end
|
||||
end
|
||||
|
||||
def basename(file)
|
||||
relativize(file) {|f| File.basename(file)}
|
||||
end
|
||||
|
||||
def relativize(path)
|
||||
if path.index(working_path+File::SEPARATOR) == 0
|
||||
path[(working_path+File::SEPARATOR).length..-1]
|
||||
elsif block_given?
|
||||
yield path
|
||||
else
|
||||
path
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
50
lib/compass/installers/manifest.rb
Normal file
50
lib/compass/installers/manifest.rb
Normal file
@ -0,0 +1,50 @@
|
||||
module Compass
|
||||
module Installers
|
||||
|
||||
class Manifest
|
||||
|
||||
# A Manifest entry
|
||||
Entry = Struct.new(:type, :from, :options)
|
||||
|
||||
def initialize(manifest_file = nil)
|
||||
@entries = []
|
||||
parse(manifest_file) if manifest_file
|
||||
end
|
||||
|
||||
def self.type(t)
|
||||
eval <<-END
|
||||
def #{t}(from, options = {})
|
||||
@entries << Entry.new(:#{t}, from, options)
|
||||
end
|
||||
def has_#{t}?
|
||||
@entries.detect {|e| e.type == :#{t}}
|
||||
end
|
||||
END
|
||||
end
|
||||
|
||||
type :stylesheet
|
||||
type :image
|
||||
type :javascript
|
||||
type :file
|
||||
|
||||
# Enumerates over the manifest files
|
||||
def each
|
||||
@entries.each {|e| yield e}
|
||||
end
|
||||
|
||||
|
||||
protected
|
||||
# parses a manifest file which is a ruby script
|
||||
# evaluated in a Manifest instance context
|
||||
def parse(manifest_file)
|
||||
open(manifest_file) do |f|
|
||||
eval(f.read, instance_binding, manifest_file)
|
||||
end
|
||||
end
|
||||
def instance_binding
|
||||
binding
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
end
|
51
lib/compass/installers/stand_alone.rb
Normal file
51
lib/compass/installers/stand_alone.rb
Normal file
@ -0,0 +1,51 @@
|
||||
module Compass
|
||||
module Installers
|
||||
|
||||
class StandAloneInstaller < Base
|
||||
|
||||
def configure
|
||||
@config = Compass::Configuration.new
|
||||
if File.exists?(config_file)
|
||||
@config.parse(config_file)
|
||||
elsif File.exists?(old_config_file)
|
||||
@config.parse(old_config_file)
|
||||
end
|
||||
super
|
||||
end
|
||||
|
||||
def prepare
|
||||
directory ""
|
||||
directory css_dir
|
||||
directory sass_dir
|
||||
directory images_dir if manifest.has_image?
|
||||
directory javascripts_dir if manifest.has_javascript?
|
||||
end
|
||||
|
||||
def default_css_dir
|
||||
@config.css_dir || "stylesheets"
|
||||
end
|
||||
|
||||
def default_sass_dir
|
||||
@config.sass_dir ||"src"
|
||||
end
|
||||
|
||||
def default_images_dir
|
||||
@config.images_dir || "images"
|
||||
end
|
||||
|
||||
def default_javascripts_dir
|
||||
@config.javascripts_dir || "javascripts"
|
||||
end
|
||||
|
||||
# Read the configuration file for this project
|
||||
def config_file
|
||||
@config_file ||= targetize('config.rb')
|
||||
end
|
||||
|
||||
def old_config_file
|
||||
@old_config_file ||= targetize('src/config.rb')
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
end
|
Loading…
Reference in New Issue
Block a user