From b03034a686df5ed91d790404b27e595165883834 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Valim?= Date: Thu, 16 Jul 2009 10:16:23 +0200 Subject: Update vendored Thor to have latest actions updates. --- .../lib/vendor/thor-0.11.1/lib/thor/actions.rb | 108 ------------ .../thor-0.11.1/lib/thor/actions/copy_file.rb | 32 ---- .../thor-0.11.1/lib/thor/actions/create_file.rb | 59 ++++++- .../thor-0.11.1/lib/thor/actions/directory.rb | 9 +- .../lib/thor/actions/empty_directory.rb | 113 +++++++++++- .../lib/thor/actions/file_manipulation.rb | 194 +++++++++++++++++++++ .../lib/vendor/thor-0.11.1/lib/thor/actions/get.rb | 58 ------ .../lib/thor/actions/inject_into_file.rb | 29 +-- .../thor-0.11.1/lib/thor/actions/template.rb | 38 ---- .../thor-0.11.1/lib/thor/actions/templater.rb | 194 --------------------- 10 files changed, 371 insertions(+), 463 deletions(-) delete mode 100644 railties/lib/vendor/thor-0.11.1/lib/thor/actions/copy_file.rb create mode 100644 railties/lib/vendor/thor-0.11.1/lib/thor/actions/file_manipulation.rb delete mode 100644 railties/lib/vendor/thor-0.11.1/lib/thor/actions/get.rb delete mode 100644 railties/lib/vendor/thor-0.11.1/lib/thor/actions/template.rb delete mode 100644 railties/lib/vendor/thor-0.11.1/lib/thor/actions/templater.rb (limited to 'railties') diff --git a/railties/lib/vendor/thor-0.11.1/lib/thor/actions.rb b/railties/lib/vendor/thor-0.11.1/lib/thor/actions.rb index 44dfa1b14c..ff0592ea1b 100644 --- a/railties/lib/vendor/thor-0.11.1/lib/thor/actions.rb +++ b/railties/lib/vendor/thor-0.11.1/lib/thor/actions.rb @@ -159,24 +159,6 @@ class Thor inside(@destination_stack.first) { yield } end - # Changes the mode of the given file or directory. - # - # ==== Parameters - # mode:: the file mode - # path:: the name of the file to change mode - # config:: give :verbose => false to not log the status. - # - # ==== Example - # - # chmod "script/*", 0755 - # - def chmod(path, mode, config={}) - return unless behavior == :invoke - path = File.expand_path(path, destination_root) - say_status :chmod, relative_to_original_destination_root(path), config.fetch(:verbose, true) - FileUtils.chmod_R(mode, path) unless options[:pretend] - end - # Executes a command. # # ==== Parameters @@ -237,96 +219,6 @@ class Thor run "thor #{command}", :verbose => false end - # Removes a file at the given location. - # - # ==== Parameters - # path:: path of the file to be changed - # config:: give :verbose => false to not log the status. - # - # ==== Example - # - # remove_file 'README' - # remove_file 'app/controllers/application_controller.rb' - # - def remove_file(path, config={}) - return unless behavior == :invoke - path = File.expand_path(path, destination_root) - - say_status :remove, relative_to_original_destination_root(path), config.fetch(:verbose, true) - ::FileUtils.rm_rf(path) if !options[:pretend] && File.exists?(path) - end - - # Run a regular expression replacement on a file. - # - # ==== Parameters - # path:: path of the file to be changed - # flag:: the regexp or string to be replaced - # replacement:: the replacement, can be also given as a block - # config:: give :verbose => false to not log the status. - # - # ==== Example - # - # gsub_file 'app/controllers/application_controller.rb', /#\s*(filter_parameter_logging :password)/, '\1' - # - # gsub_file 'README', /rake/, :green do |match| - # match << " no more. Use thor!" - # end - # - def gsub_file(path, flag, *args, &block) - return unless behavior == :invoke - config = args.last.is_a?(Hash) ? args.pop : {} - - path = File.expand_path(path, destination_root) - say_status :gsub, relative_to_original_destination_root(path), config.fetch(:verbose, true) - - unless options[:pretend] - content = File.read(path) - content.gsub!(flag, *args, &block) - File.open(path, 'wb') { |file| file.write(content) } - end - end - - # Append text to a file. - # - # ==== Parameters - # path:: path of the file to be changed - # data:: the data to append to the file, can be also given as a block. - # config:: give :verbose => false to not log the status. - # - # ==== Example - # - # append_file 'config/environments/test.rb', 'config.gem "rspec"' - # - def append_file(path, data=nil, config={}, &block) - return unless behavior == :invoke - path = File.expand_path(path, destination_root) - say_status :append, relative_to_original_destination_root(path), config.fetch(:verbose, true) - File.open(path, 'ab') { |file| file.write(data || block.call) } unless options[:pretend] - end - - # Prepend text to a file. - # - # ==== Parameters - # path:: path of the file to be changed - # data:: the data to prepend to the file, can be also given as a block. - # config:: give :verbose => false to not log the status. - # - # ==== Example - # - # prepend_file 'config/environments/test.rb', 'config.gem "rspec"' - # - def prepend_file(path, data=nil, config={}, &block) - return unless behavior == :invoke - path = File.expand_path(path, destination_root) - say_status :prepend, relative_to_original_destination_root(path), config.fetch(:verbose, true) - - unless options[:pretend] - content = data || block.call - content << File.read(path) - File.open(path, 'wb') { |file| file.write(content) } - end - end - protected # Allow current root to be shared between invocations. diff --git a/railties/lib/vendor/thor-0.11.1/lib/thor/actions/copy_file.rb b/railties/lib/vendor/thor-0.11.1/lib/thor/actions/copy_file.rb deleted file mode 100644 index bfbc38a367..0000000000 --- a/railties/lib/vendor/thor-0.11.1/lib/thor/actions/copy_file.rb +++ /dev/null @@ -1,32 +0,0 @@ -require 'thor/actions/templater' - -class Thor - module Actions - - # Copies the file from the relative source to the relative destination. If - # the destination is not given it's assumed to be equal to the source. - # - # ==== Parameters - # source:: the relative path to the source root. - # destination:: the relative path to the destination root. - # config:: give :verbose => false to not log the status. - # - # ==== Examples - # - # copy_file "README", "doc/README" - # - # copy_file "doc/README" - # - def copy_file(source, destination=nil, config={}) - action CopyFile.new(self, source, destination || source, config) - end - - class CopyFile < Templater #:nodoc: - - def render - @render ||= ::File.read(source) - end - - end - end -end diff --git a/railties/lib/vendor/thor-0.11.1/lib/thor/actions/create_file.rb b/railties/lib/vendor/thor-0.11.1/lib/thor/actions/create_file.rb index 72bf34c0a3..8f6badee27 100644 --- a/railties/lib/vendor/thor-0.11.1/lib/thor/actions/create_file.rb +++ b/railties/lib/vendor/thor-0.11.1/lib/thor/actions/create_file.rb @@ -1,4 +1,4 @@ -require 'thor/actions/templater' +require 'thor/actions/empty_directory' class Thor module Actions @@ -28,14 +28,25 @@ class Thor # AddFile is a subset of Template, which instead of rendering a file with # ERB, it gets the content from the user. # - class CreateFile < Templater #:nodoc: + class CreateFile < EmptyDirectory #:nodoc: attr_reader :data def initialize(base, destination, data, config={}) - super(base, nil, destination, config) @data = data + super(base, destination, config) end + # Checks if the content of the file at the destination is identical to the rendered result. + # + # ==== Returns + # Boolean:: true if it is identical, false otherwise. + # + def identical? + exists? && File.read(destination) == render + end + + # Holds the content to be added to the file. + # def render @render ||= if data.is_a?(Proc) data.call @@ -44,6 +55,48 @@ class Thor end end + def invoke! + invoke_with_conflict_check do + FileUtils.mkdir_p(File.dirname(destination)) + File.open(destination, 'w'){ |f| f.write render } + end + end + + protected + + # Now on conflict we check if the file is identical or not. + # + def on_conflict_behavior(&block) + if identical? + say_status :identical, :blue + else + options = base.options.merge(config) + force_or_skip_or_conflict(options[:force], options[:skip], &block) + end + end + + # If force is true, run the action, otherwise check if it's not being + # skipped. If both are false, show the file_collision menu, if the menu + # returns true, force it, otherwise skip. + # + def force_or_skip_or_conflict(force, skip, &block) + if force + say_status :force, :yellow + block.call unless pretend? + elsif skip + say_status :skip, :yellow + else + say_status :conflict, :red + force_or_skip_or_conflict(force_on_collision?, true, &block) + end + end + + # Shows the file collision menu to the user and gets the result. + # + def force_on_collision? + base.shell.file_collision(destination){ render } + end + end end end diff --git a/railties/lib/vendor/thor-0.11.1/lib/thor/actions/directory.rb b/railties/lib/vendor/thor-0.11.1/lib/thor/actions/directory.rb index 2c6d2bc59b..e33639f4e5 100644 --- a/railties/lib/vendor/thor-0.11.1/lib/thor/actions/directory.rb +++ b/railties/lib/vendor/thor-0.11.1/lib/thor/actions/directory.rb @@ -1,4 +1,4 @@ -require 'thor/actions/templater' +require 'thor/actions/empty_directory' class Thor module Actions @@ -44,9 +44,12 @@ class Thor action Directory.new(self, source, destination || source, config) end - class Directory < Templater #:nodoc: + class Directory < EmptyDirectory #:nodoc: + attr_reader :source + def initialize(base, source, destination=nil, config={}) - super(base, source, destination, { :recursive => true }.merge(config)) + @source = File.expand_path(base.find_in_source_paths(source.to_s)) + super(base, destination, { :recursive => true }.merge(config)) end def invoke! diff --git a/railties/lib/vendor/thor-0.11.1/lib/thor/actions/empty_directory.rb b/railties/lib/vendor/thor-0.11.1/lib/thor/actions/empty_directory.rb index 04f9817212..03c1fe4af1 100644 --- a/railties/lib/vendor/thor-0.11.1/lib/thor/actions/empty_directory.rb +++ b/railties/lib/vendor/thor-0.11.1/lib/thor/actions/empty_directory.rb @@ -1,5 +1,3 @@ -require 'thor/actions/templater' - class Thor module Actions @@ -14,17 +12,122 @@ class Thor # empty_directory "doc" # def empty_directory(destination, config={}) - action EmptyDirectory.new(self, nil, destination, config) + action EmptyDirectory.new(self, destination, config) end - class EmptyDirectory < Templater #:nodoc: + # Class which holds create directory logic. This is the base class for + # other actions like create_file and directory. + # + # This implementation is based in Templater actions, created by Jonas Nicklas + # and Michael S. Klishin under MIT LICENSE. + # + class EmptyDirectory #:nodoc: + attr_reader :base, :destination, :given_destination, :relative_destination, :config + + # Initializes given the source and destination. + # + # ==== Parameters + # base:: A Thor::Base instance + # source:: Relative path to the source of this file + # destination:: Relative path to the destination of this file + # config:: give :verbose => false to not log the status. + # + def initialize(base, destination, config={}) + @base, @config = base, { :verbose => true }.merge(config) + self.destination = destination + end + + # Checks if the destination file already exists. + # + # ==== Returns + # Boolean:: true if the file exists, false otherwise. + # + def exists? + ::File.exists?(destination) + end def invoke! - invoke_with_options!(base.options.merge(config)) do + invoke_with_conflict_check do ::FileUtils.mkdir_p(destination) end end + def revoke! + say_status :remove, :red + ::FileUtils.rm_rf(destination) if !pretend? && exists? + end + + protected + + # Shortcut for pretend. + # + def pretend? + base.options[:pretend] + end + + # Sets the absolute destination value from a relative destination value. + # It also stores the given and relative destination. Let's suppose our + # script is being executed on "dest", it sets the destination root to + # "dest". The destination, given_destination and relative_destination + # are related in the following way: + # + # inside "bar" do + # empty_directory "baz" + # end + # + # destination #=> dest/bar/baz + # relative_destination #=> bar/baz + # given_destination #=> baz + # + def destination=(destination) + if destination + @given_destination = convert_encoded_instructions(destination.to_s) + @destination = ::File.expand_path(@given_destination, base.destination_root) + @relative_destination = base.relative_to_original_destination_root(@destination) + end + end + + # Filenames in the encoded form are converted. If you have a file: + # + # %class_name%.rb + # + # It gets the class name from the base and replace it: + # + # user.rb + # + def convert_encoded_instructions(filename) + filename.gsub(/%(.*?)%/) do |string| + instruction = $1.strip + base.respond_to?(instruction) ? base.send(instruction) : string + end + end + + # Receives a hash of options and just execute the block if some + # conditions are met. + # + def invoke_with_conflict_check(&block) + if exists? + on_conflict_behavior(&block) + else + say_status :create, :green + block.call unless pretend? + end + + destination + end + + # What to do when the destination file already exists. + # + def on_conflict_behavior(&block) + say_status :exist, :blue + end + + # Shortcut to say_status shell method. + # + def say_status(status, color) + base.shell.say_status status, relative_destination, color if config[:verbose] + end + end end end diff --git a/railties/lib/vendor/thor-0.11.1/lib/thor/actions/file_manipulation.rb b/railties/lib/vendor/thor-0.11.1/lib/thor/actions/file_manipulation.rb new file mode 100644 index 0000000000..5a39840404 --- /dev/null +++ b/railties/lib/vendor/thor-0.11.1/lib/thor/actions/file_manipulation.rb @@ -0,0 +1,194 @@ +require 'erb' +require 'open-uri' + +class Thor + module Actions + + # Copies the file from the relative source to the relative destination. If + # the destination is not given it's assumed to be equal to the source. + # + # ==== Parameters + # source:: the relative path to the source root. + # destination:: the relative path to the destination root. + # config:: give :verbose => false to not log the status. + # + # ==== Examples + # + # copy_file "README", "doc/README" + # + # copy_file "doc/README" + # + def copy_file(source, destination=nil, config={}) + destination ||= source + source = File.expand_path(find_in_source_paths(source.to_s)) + + create_file destination, nil, config do + File.read(source) + end + end + + # Gets the content at the given address and places it at the given relative + # destination. If a block is given instead of destination, the content of + # the url is yielded and used as location. + # + # ==== Parameters + # source:: the address of the given content. + # destination:: the relative path to the destination root. + # config:: give :verbose => false to not log the status. + # + # ==== Examples + # + # get "http://gist.github.com/103208", "doc/README" + # + # get "http://gist.github.com/103208" do |content| + # content.split("\n").first + # end + # + def get(source, destination=nil, config={}, &block) + source = File.expand_path(find_in_source_paths(source.to_s)) unless source =~ /^http\:\/\// + render = open(source).read + + destination ||= if block_given? + block.arity == 1 ? block.call(render) : block.call + else + File.basename(source) + end + + create_file destination, render, config + end + + # Gets an ERB template at the relative source, executes it and makes a copy + # at the relative destination. If the destination is not given it's assumed + # to be equal to the source removing .tt from the filename. + # + # ==== Parameters + # source:: the relative path to the source root. + # destination:: the relative path to the destination root. + # config:: give :verbose => false to not log the status. + # + # ==== Examples + # + # template "README", "doc/README" + # + # template "doc/README" + # + def template(source, destination=nil, config={}) + destination ||= source + source = File.expand_path(find_in_source_paths(source.to_s)) + context = instance_eval('binding') + + create_file destination, nil, config do + ERB.new(::File.read(source), nil, '-').result(context) + end + end + + # Changes the mode of the given file or directory. + # + # ==== Parameters + # mode:: the file mode + # path:: the name of the file to change mode + # config:: give :verbose => false to not log the status. + # + # ==== Example + # + # chmod "script/*", 0755 + # + def chmod(path, mode, config={}) + return unless behavior == :invoke + path = File.expand_path(path, destination_root) + say_status :chmod, relative_to_original_destination_root(path), config.fetch(:verbose, true) + FileUtils.chmod_R(mode, path) unless options[:pretend] + end + + # Prepend text to a file. + # + # ==== Parameters + # path:: path of the file to be changed + # data:: the data to prepend to the file, can be also given as a block. + # config:: give :verbose => false to not log the status. + # + # ==== Example + # + # prepend_file 'config/environments/test.rb', 'config.gem "rspec"' + # + def prepend_file(path, data=nil, config={}, &block) + return unless behavior == :invoke + path = File.expand_path(path, destination_root) + say_status :prepend, relative_to_original_destination_root(path), config.fetch(:verbose, true) + + unless options[:pretend] + content = data || block.call + content << File.read(path) + File.open(path, 'wb') { |file| file.write(content) } + end + end + + # Append text to a file. + # + # ==== Parameters + # path:: path of the file to be changed + # data:: the data to append to the file, can be also given as a block. + # config:: give :verbose => false to not log the status. + # + # ==== Example + # + # append_file 'config/environments/test.rb', 'config.gem "rspec"' + # + def append_file(path, data=nil, config={}, &block) + return unless behavior == :invoke + path = File.expand_path(path, destination_root) + say_status :append, relative_to_original_destination_root(path), config.fetch(:verbose, true) + File.open(path, 'ab') { |file| file.write(data || block.call) } unless options[:pretend] + end + + # Run a regular expression replacement on a file. + # + # ==== Parameters + # path:: path of the file to be changed + # flag:: the regexp or string to be replaced + # replacement:: the replacement, can be also given as a block + # config:: give :verbose => false to not log the status. + # + # ==== Example + # + # gsub_file 'app/controllers/application_controller.rb', /#\s*(filter_parameter_logging :password)/, '\1' + # + # gsub_file 'README', /rake/, :green do |match| + # match << " no more. Use thor!" + # end + # + def gsub_file(path, flag, *args, &block) + return unless behavior == :invoke + config = args.last.is_a?(Hash) ? args.pop : {} + + path = File.expand_path(path, destination_root) + say_status :gsub, relative_to_original_destination_root(path), config.fetch(:verbose, true) + + unless options[:pretend] + content = File.read(path) + content.gsub!(flag, *args, &block) + File.open(path, 'wb') { |file| file.write(content) } + end + end + + # Removes a file at the given location. + # + # ==== Parameters + # path:: path of the file to be changed + # config:: give :verbose => false to not log the status. + # + # ==== Example + # + # remove_file 'README' + # remove_file 'app/controllers/application_controller.rb' + # + def remove_file(path, config={}) + return unless behavior == :invoke + path = File.expand_path(path, destination_root) + + say_status :remove, relative_to_original_destination_root(path), config.fetch(:verbose, true) + ::FileUtils.rm_rf(path) if !options[:pretend] && File.exists?(path) + end + + end +end diff --git a/railties/lib/vendor/thor-0.11.1/lib/thor/actions/get.rb b/railties/lib/vendor/thor-0.11.1/lib/thor/actions/get.rb deleted file mode 100644 index bd8deb8194..0000000000 --- a/railties/lib/vendor/thor-0.11.1/lib/thor/actions/get.rb +++ /dev/null @@ -1,58 +0,0 @@ -require 'thor/actions/templater' -require 'open-uri' - -class Thor - module Actions - - # Gets the content at the given address and places it at the given relative - # destination. If a block is given instead of destination, the content of - # the url is yielded and used as location. - # - # ==== Parameters - # source:: the address of the given content. - # destination:: the relative path to the destination root. - # config:: give :verbose => false to not log the status. - # - # ==== Examples - # - # get "http://gist.github.com/103208", "doc/README" - # - # get "http://gist.github.com/103208" do |content| - # content.split("\n").first - # end - # - def get(source, destination=nil, config={}, &block) - action Get.new(self, source, block || destination, config) - end - - class Get < Templater #:nodoc: - - def render - @render ||= open(source).read - end - - protected - - def source=(source) - if source =~ /^http\:\/\// - @source = source - else - super(source) - end - end - - def destination=(destination) - destination = if destination.nil? - File.basename(source) - elsif destination.is_a?(Proc) - destination.arity == 1 ? destination.call(render) : destination.call - else - destination - end - - super(destination) - end - - end - end -end diff --git a/railties/lib/vendor/thor-0.11.1/lib/thor/actions/inject_into_file.rb b/railties/lib/vendor/thor-0.11.1/lib/thor/actions/inject_into_file.rb index 6bd0100a12..089bd894e4 100644 --- a/railties/lib/vendor/thor-0.11.1/lib/thor/actions/inject_into_file.rb +++ b/railties/lib/vendor/thor-0.11.1/lib/thor/actions/inject_into_file.rb @@ -1,3 +1,5 @@ +require 'thor/actions/empty_directory' + class Thor module Actions @@ -32,13 +34,12 @@ class Thor action InjectIntoFile.new(self, destination, data, config) end - class InjectIntoFile #:nodoc: - attr_reader :base, :destination, :relative_destination, :flag, :replacement, :config + class InjectIntoFile < EmptyDirectory + attr_reader :flag, :replacement def initialize(base, destination, data, config) - @base, @config = base, { :verbose => true }.merge(config) + super(base, destination, { :verbose => true }.merge(config)) - self.destination = destination data = data.call if data.is_a?(Proc) @replacement = if @config.key?(:after) @@ -51,33 +52,17 @@ class Thor end def invoke! - say_status :inject + say_status :inject, config[:verbose] replace!(flag, replacement) end def revoke! - say_status :deinject + say_status :deinject, config[:verbose] replace!(replacement, flag) end protected - # Sets the destination value from a relative destination value. The - # relative destination is kept to be used in output messages. - # - def destination=(destination) - if destination - @destination = ::File.expand_path(destination.to_s, base.destination_root) - @relative_destination = base.relative_to_original_destination_root(@destination) - end - end - - # Shortcut to say_status shell method. - # - def say_status(status) - base.shell.say_status status, relative_destination, config[:verbose] - end - # Adds the content to the file. # def replace!(regexp, string) diff --git a/railties/lib/vendor/thor-0.11.1/lib/thor/actions/template.rb b/railties/lib/vendor/thor-0.11.1/lib/thor/actions/template.rb deleted file mode 100644 index 95e2412514..0000000000 --- a/railties/lib/vendor/thor-0.11.1/lib/thor/actions/template.rb +++ /dev/null @@ -1,38 +0,0 @@ -require 'thor/actions/templater' -require 'erb' - -class Thor - module Actions - - # Gets an ERB template at the relative source, executes it and makes a copy - # at the relative destination. If the destination is not given it's assumed - # to be equal to the source removing .tt from the filename. - # - # ==== Parameters - # source:: the relative path to the source root. - # destination:: the relative path to the destination root. - # config:: give :verbose => false to not log the status. - # - # ==== Examples - # - # template "README", "doc/README" - # - # template "doc/README" - # - def template(source, destination=nil, config={}) - destination ||= source.gsub(/.tt$/, '') - action Template.new(self, source, destination, config) - end - - class Template < Templater #:nodoc: - - def render - @render ||= begin - context = base.instance_eval('binding') - ERB.new(::File.read(source), nil, '-').result(context) - end - end - - end - end -end diff --git a/railties/lib/vendor/thor-0.11.1/lib/thor/actions/templater.rb b/railties/lib/vendor/thor-0.11.1/lib/thor/actions/templater.rb deleted file mode 100644 index 455178c6e8..0000000000 --- a/railties/lib/vendor/thor-0.11.1/lib/thor/actions/templater.rb +++ /dev/null @@ -1,194 +0,0 @@ -class Thor - module Actions - - # This is the base class for templater actions, ie. that copies something - # from some directory (source) to another (destination). - # - # This implementation is completely based in Templater actions, created - # by Jonas Nicklas and Michael S. Klishin under MIT LICENSE. - # - class Templater #:nodoc: - attr_reader :base, :source, :destination, :given_destination, :relative_destination, :config - - # Initializes given the source and destination. - # - # ==== Parameters - # base:: A Thor::Base instance - # source:: Relative path to the source of this file - # destination:: Relative path to the destination of this file - # config:: give :verbose => false to not log the status. - # - def initialize(base, source, destination, config={}) - @base, @config = base, { :verbose => true }.merge(config) - self.source = source - self.destination = destination - end - - # Returns the contents of the source file as a String. If render is - # available, a diff option is shown in the file collision menu. - # - # ==== Returns - # String:: The source file. - # - # def render - # end - - # Checks if the destination file already exists. - # - # ==== Returns - # Boolean:: true if the file exists, false otherwise. - # - def exists? - ::File.exists?(destination) - end - - # Checks if the content of the file at the destination is identical to the rendered result. - # - # ==== Returns - # Boolean:: true if it is identical, false otherwise. - # - def identical? - exists? && (is_not_comparable? || ::File.read(destination) == render) - end - - # Invokes the action. By default it adds to the file the content rendered, - # but you can modify in the subclass. - # - def invoke! - invoke_with_options!(base.options.merge(config)) do - ::FileUtils.mkdir_p(::File.dirname(destination)) - ::File.open(destination, 'w'){ |f| f.write render } - end - end - - # Revokes the action. - # - def revoke! - say_status :remove, :red - ::FileUtils.rm_rf(destination) if !pretend? && exists? - end - - protected - - # Shortcut for pretend. - # - def pretend? - base.options[:pretend] - end - - # A templater is comparable if responds to render. In such cases, we have - # to show the conflict menu to the user unless the files are identical. - # - def is_not_comparable? - !respond_to?(:render) - end - - # Sets the absolute source value from a relative source value. Notice - # that we need to take into consideration both the source_root as the - # relative_root. - # - # Let's suppose that we are on the directory "dest", with source root set - # to "source" and with the following scenario: - # - # inside "bar" do - # copy_file "baz.rb" - # end - # - # In this case, the user wants to copy the file at "source/bar/baz.rb" - # to "dest/bar/baz.rb". If we don't take into account the relative_root - # (in this case, "bar"), it would copy the contents at "source/baz.rb". - # - def source=(source) - if source - @source = ::File.expand_path(base.find_in_source_paths(source.to_s)) - end - end - - # Sets the absolute destination value from a relative destination value. - # It also stores the given and relative destination. Let's suppose our - # script is being executed on "dest", it sets the destination root to - # "dest". The destination, given_destination and relative_destination - # are related in the following way: - # - # inside "bar" do - # empty_directory "baz" - # end - # - # destination #=> dest/bar/baz - # relative_destination #=> bar/baz - # given_destination #=> baz - # - def destination=(destination) - if destination - @given_destination = convert_encoded_instructions(destination.to_s) - @destination = ::File.expand_path(@given_destination, base.destination_root) - @relative_destination = base.relative_to_original_destination_root(@destination) - end - end - - # Filenames in the encoded form are converted. If you have a file: - # - # %class_name%.rb - # - # It gets the class name from the base and replace it: - # - # user.rb - # - def convert_encoded_instructions(filename) - filename.gsub(/%(.*?)%/) do |string| - instruction = $1.strip - base.respond_to?(instruction) ? base.send(instruction) : string - end - end - - # Receives a hash of options and just execute the block if some - # conditions are met. - # - def invoke_with_options!(options, &block) - if exists? - if is_not_comparable? - say_status :exist, :blue - elsif identical? - say_status :identical, :blue - else - force_or_skip_or_conflict(options[:force], options[:skip], &block) - end - else - say_status :create, :green - block.call unless pretend? - end - - destination - end - - # If force is true, run the action, otherwise check if it's not being - # skipped. If both are false, show the file_collision menu, if the menu - # returns true, force it, otherwise skip. - # - def force_or_skip_or_conflict(force, skip, &block) - if force - say_status :force, :yellow - block.call unless pretend? - elsif skip - say_status :skip, :yellow - else - say_status :conflict, :red - force_or_skip_or_conflict(force_on_collision?, true, &block) - end - end - - # Shows the file collision menu to the user and gets the result. - # - def force_on_collision? - base.shell.file_collision(destination){ render } - end - - # Shortcut to say_status shell method. - # - def say_status(status, color) - base.shell.say_status status, relative_destination, color if config[:verbose] - end - - end - end -end -- cgit v1.2.3