From 1e5502159bad4fd43146aba35fdf3e6a8e359420 Mon Sep 17 00:00:00 2001 From: Chris Eppstein Date: Sun, 25 Jan 2009 14:27:08 -0800 Subject: [PATCH] Refactor the Compass commands to centralize and cleanup the project commands. --- lib/compass/commands/base.rb | 30 +++++---- lib/compass/commands/create_project.rb | 30 +++++---- lib/compass/commands/install_rails.rb | 38 +++-------- lib/compass/commands/project_base.rb | 89 ++++++++++++++++++++++++++ lib/compass/commands/update_project.rb | 41 +----------- lib/compass/exec.rb | 3 + test/command_line_test.rb | 1 + 7 files changed, 142 insertions(+), 90 deletions(-) create mode 100644 lib/compass/commands/project_base.rb diff --git a/lib/compass/commands/base.rb b/lib/compass/commands/base.rb index 6d09c8f8..aff5127d 100644 --- a/lib/compass/commands/base.rb +++ b/lib/compass/commands/base.rb @@ -12,19 +12,23 @@ module Compass end protected - - def projectize(path) - File.join(project_directory, separate(path)) + + def relativize(path) + if path.index(working_directory+File::SEPARATOR) == 0 + path[(working_directory+File::SEPARATOR).length..-1] + else + path + end end + # create a directory and all the directories necessary to reach it. - def directory(subdir, options = nil) + def directory(dir, options = nil) options ||= self.options - dir = subdir ? projectize(subdir) : project_directory if File.exists?(dir) && File.directory?(dir) && options[:force] print_action :exists, basename(dir) + File::SEPARATOR elsif File.exists?(dir) && File.directory?(dir) - msg = "Directory #{basename(dir)} already exists. Run with --force to force project creation." - raise ::Compass::Exec::ExecError.new(msg) + msg = "Directory #{basename(dir)} already exists. Run with --force to force creation." + raise ::Compass::Exec::DirectoryExistsError.new(msg) elsif File.exists?(dir) msg = "#{basename(dir)} already exists and is not a directory." raise ::Compass::Exec::ExecError.new(msg) @@ -34,9 +38,13 @@ module Compass end end + def absolute_path?(path) + # This is only going to work on unix, gonna need a better implementation. + path.index(File::SEPARATOR) == 0 + end + # copy/process a template in the compass template directory to the project directory. def template(from, to, options) - to = projectize(to) from = File.join(templates_directory, separate(from)) if File.exists?(to) && !options[:force] #TODO: Detect differences & provide an overwrite prompt @@ -75,9 +83,9 @@ module Compass path.gsub(%r{/}, File::SEPARATOR) end - def basename(file, extra = 0) - if file.length > (working_directory.length + extra) - file[(working_directory.length + extra + 1)..-1] + def basename(file) + if file.length > working_directory.length + relativize(file) else File.basename(file) end diff --git a/lib/compass/commands/create_project.rb b/lib/compass/commands/create_project.rb index 5c850b08..75a205db 100644 --- a/lib/compass/commands/create_project.rb +++ b/lib/compass/commands/create_project.rb @@ -4,33 +4,41 @@ require File.join(File.dirname(__FILE__), 'update_project') module Compass module Commands - class CreateProject < Base + class CreateProject < ProjectBase - attr_accessor :project_directory, :project_name - def initialize(working_directory, options) super(working_directory, options) - self.project_name = options[:project_name] - self.project_directory = File.expand_path File.join(working_directory, project_name) end # all commands must implement perform def perform - directory nil, options + 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) - project_dir = File.join(templates_directory, "project") - templates = Dir.chdir(project_dir) do - Dir.glob("*") - end - templates.each do |t| + framework_templates.each do |t| template "project/#{t}", "#{src_dir}/#{t}", options end 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 + end + + def skip_project_directory_assertion? + true + end + end end end \ No newline at end of file diff --git a/lib/compass/commands/install_rails.rb b/lib/compass/commands/install_rails.rb index 0f620456..b6b99998 100644 --- a/lib/compass/commands/install_rails.rb +++ b/lib/compass/commands/install_rails.rb @@ -2,42 +2,26 @@ require File.join(File.dirname(__FILE__), 'base') module Compass module Commands - class InstallRails < Base - def initialize(working_directory, options) - wd = options[:project_name] ? File.join(working_directory, options.delete(:project_name)) : working_directory - super(wd, options) + class InstallRails < CreateProject + def initialize(*args) + super end + def perform set_install_location set_output_location directory options[:stylesheets_location] - template 'project/screen.sass', "#{options[:stylesheets_location]}/screen.sass", options - template 'project/print.sass', "#{options[:stylesheets_location]}/print.sass", options - template 'project/ie.sass', "#{options[:stylesheets_location]}/ie.sass", options - write_file projectize('config/initializers/compass.rb'), initializer_contents + framework_templates.each do |t| + template "project/#{t}", "#{options[:stylesheets_location]}/#{t}", options + end + write_file 'config/initializers/compass.rb', initializer_contents if has_application_layout? next_steps else - write_file projectize('app/views/layouts/application.html.haml'), application_layout_contents + write_file 'app/views/layouts/application.html.haml', application_layout_contents end end - def initializer - init_file = - if File.exists?(init_file) && !options[:force] - msg = "File #{basename(init_file)} already exists. Run with --force to force project creation." - raise ::Compass::Exec::ExecError.new(msg) - end - if File.exists?(init_file) - print_action :overwrite, basename(init_file) - else - print_action :create, basename(init_file) - end - output = open(init_file,'w') - output.write(initializer_contents) - output.close - end - def initializer_contents %Q{require 'compass' # If you have any compass plugins, require them here. @@ -97,10 +81,6 @@ NEXTSTEPS end end - def project_directory - working_directory - end - def set_install_location print "Compass recommends that you keep your stylesheets in app/stylesheets/ instead of the Sass default location of public/stylesheets/sass/.\nIs this OK? (Y/n) " answer = gets diff --git a/lib/compass/commands/project_base.rb b/lib/compass/commands/project_base.rb new file mode 100644 index 00000000..f5575d2c --- /dev/null +++ b/lib/compass/commands/project_base.rb @@ -0,0 +1,89 @@ +require 'rubygems' +require 'sass' +require 'fileutils' +require 'pathname' +require File.join(File.dirname(__FILE__), 'base') + +module Compass + module Commands + class ProjectBase < Base + attr_accessor :project_directory, :project_name, :options, :project_src_subdirectory, :project_css_subdirectory + + def initialize(working_directory, options = {}) + super(working_directory, options) + self.project_name = determine_project_name(working_directory, options) + self.project_directory = determine_project_directory(working_directory, options) + assert_project_directory_exists! + end + + protected + + def directory(subdir, options = nil) + subdir ||= project_directory + subdir = projectize(subdir) unless absolute_path?(subdir) + super(subdir, options) + end + + def template(from, to, options) + to = projectize(to) unless absolute_path?(to) + super(from, to, options) + end + + def write_file(path, contents) + path = projectize(path) unless absolute_path?(path) + super(path, contents) + end + + def projectize(path) + File.join(project_directory, separate(path)) + end + + # Read the configuration file for this project + def read_project_configuration + config_file = projectize('src/config.rb') + if File.exists?(config_file) + contents = open(config_file) {|f| f.read} + eval(contents, nil, config_file) + end + end + + private + + def determine_project_name(working_directory, options) + if options[:project_name] + File.basename(strip_trailing_separator(options[:project_name])) + else + File.basename(working_directory) + end + end + + def determine_project_directory(working_directory, options) + if options[:project_name] + if absolute_path?(options[:project_name]) + options[:project_name] + else + File.join(working_directory, options[:project_name]) + end + else + working_directory + end + end + + def assert_project_directory_exists! + if File.exists?(project_directory) && !File.directory?(project_directory) + raise Compass::Exec::ExecError.new("#{project_directory} is not a directory.") + elsif !File.directory?(project_directory) && !skip_project_directory_assertion? + raise ::Compass::Exec::ExecError.new("#{project_directory} does not exist.") + end + end + + def skip_project_directory_assertion? + options[:force] || options[:dry_run] + end + + def strip_trailing_separator(path) + (path[-1..-1] == File::SEPARATOR) ? path[0..-2] : path + end + end + end +end \ No newline at end of file diff --git a/lib/compass/commands/update_project.rb b/lib/compass/commands/update_project.rb index ff9cde3a..ab36e69b 100644 --- a/lib/compass/commands/update_project.rb +++ b/lib/compass/commands/update_project.rb @@ -1,40 +1,12 @@ -require 'rubygems' -require 'sass' -require 'fileutils' -require 'pathname' -require File.join(File.dirname(__FILE__), 'base') +require File.join(File.dirname(__FILE__), 'project_base') module Compass module Commands - class UpdateProject < Base + class UpdateProject < ProjectBase Base::ACTIONS << :compile Base::ACTIONS << :overwrite - attr_accessor :project_directory, :project_name, :options, :project_src_subdirectory, :project_css_subdirectory - - def initialize(working_directory, options = {}) - super(working_directory, options) - if options[:project_name] - options[:project_name] = options[:project_name][0..-2] if options[:project_name][-1..-1] == File::SEPARATOR - self.project_name = File.basename(options[:project_name]) - if options[:project_name][0] == File::SEPARATOR - self.project_directory = options[:project_name] - elsif File.directory?(File.join(working_directory, options[:project_name])) - self.project_directory = File.expand_path(File.join(working_directory, options[:project_name])) - else - if File.exists?(options[:project_name]) or File.exists?(File.join(working_directory, options[:project_name])) - raise ::Compass::Exec::ExecError.new("#{options[:project_name]} is not a directory.") - elsif !(options[:force] || options[:dry_run]) - raise ::Compass::Exec::ExecError.new("#{options[:project_name]} does not exist.") - end - end - else - self.project_name = File.basename(working_directory) - self.project_directory = working_directory - end - end - def perform read_project_configuration Dir.glob(separate("#{project_src_directory}/**/[^_]*.sass")).each do |sass_file| @@ -77,15 +49,6 @@ module Compass end end - # Read the configuration file for this project - def read_project_configuration - config_file = projectize('src/config.rb') - if File.exists?(config_file) - contents = open(config_file) {|f| f.read} - eval(contents, nil, config_file) - end - end - # where to load sass files from def sass_load_paths @sass_load_paths ||= [project_src_directory] + Compass::Frameworks::ALL.map{|f| f.stylesheets_directory} diff --git a/lib/compass/exec.rb b/lib/compass/exec.rb index 51578300..97f6e0e9 100644 --- a/lib/compass/exec.rb +++ b/lib/compass/exec.rb @@ -7,6 +7,9 @@ module Compass class ExecError < StandardError end + class DirectoryExistsError < ExecError + end + def report_error(e, options) $stderr.puts "#{e.class} on line #{get_line e} of #{get_file e}: #{e.message}" diff --git a/test/command_line_test.rb b/test/command_line_test.rb index cf148f89..30176875 100644 --- a/test/command_line_test.rb +++ b/test/command_line_test.rb @@ -55,6 +55,7 @@ class CommandLineTest < Test::Unit::TestCase assert_action_performed :create, "app/stylesheets/screen.sass" assert_action_performed :create, "config/initializers/compass.rb" assert_action_performed :create, "app/views/layouts/application.html.haml" + assert_action_performed :create, "config/initializers/compass.rb" end end rescue LoadError