engineyard-serverside 2.0.0 → 2.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (36) hide show
  1. data/lib/engineyard-serverside/paths.rb +0 -1
  2. data/lib/engineyard-serverside/version.rb +1 -1
  3. data/lib/vendor/thor/{LICENSE → LICENSE.md} +2 -2
  4. data/lib/vendor/thor/README.md +28 -0
  5. data/lib/vendor/thor/lib/thor.rb +183 -48
  6. data/lib/vendor/thor/lib/thor/actions.rb +66 -23
  7. data/lib/vendor/thor/lib/thor/actions/create_file.rb +5 -3
  8. data/lib/vendor/thor/lib/thor/actions/create_link.rb +57 -0
  9. data/lib/vendor/thor/lib/thor/actions/directory.rb +14 -7
  10. data/lib/vendor/thor/lib/thor/actions/empty_directory.rb +24 -5
  11. data/lib/vendor/thor/lib/thor/actions/file_manipulation.rb +106 -21
  12. data/lib/vendor/thor/lib/thor/actions/inject_into_file.rb +15 -10
  13. data/lib/vendor/thor/lib/thor/base.rb +144 -43
  14. data/lib/vendor/thor/lib/thor/core_ext/dir_escape.rb +0 -0
  15. data/lib/vendor/thor/lib/thor/core_ext/hash_with_indifferent_access.rb +1 -1
  16. data/lib/vendor/thor/lib/thor/error.rb +6 -1
  17. data/lib/vendor/thor/lib/thor/group.rb +41 -27
  18. data/lib/vendor/thor/lib/thor/invocation.rb +48 -58
  19. data/lib/vendor/thor/lib/thor/parser/argument.rb +29 -22
  20. data/lib/vendor/thor/lib/thor/parser/arguments.rb +26 -5
  21. data/lib/vendor/thor/lib/thor/parser/option.rb +42 -49
  22. data/lib/vendor/thor/lib/thor/parser/options.rb +39 -30
  23. data/lib/vendor/thor/lib/thor/rake_compat.rb +13 -8
  24. data/lib/vendor/thor/lib/thor/runner.rb +27 -20
  25. data/lib/vendor/thor/lib/thor/shell.rb +10 -5
  26. data/lib/vendor/thor/lib/thor/shell/basic.rb +228 -78
  27. data/lib/vendor/thor/lib/thor/shell/color.rb +40 -4
  28. data/lib/vendor/thor/lib/thor/shell/html.rb +123 -0
  29. data/lib/vendor/thor/lib/thor/task.rb +83 -53
  30. data/lib/vendor/thor/lib/thor/util.rb +57 -21
  31. data/lib/vendor/thor/lib/thor/version.rb +1 -1
  32. data/lib/vendor/thor/thor.gemspec +21 -115
  33. metadata +109 -217
  34. data/lib/vendor/thor/CHANGELOG.rdoc +0 -89
  35. data/lib/vendor/thor/README.rdoc +0 -297
  36. data/lib/vendor/thor/Thorfile +0 -69
@@ -50,10 +50,46 @@ class Thor
50
50
  # on Highline implementation and it automatically appends CLEAR to the end
51
51
  # of the returned String.
52
52
  #
53
- def set_color(string, color, bold=false)
54
- color = self.class.const_get(color.to_s.upcase) if color.is_a?(Symbol)
55
- bold = bold ? BOLD : ""
56
- "#{bold}#{color}#{string}#{CLEAR}"
53
+ # Pass foreground, background and bold options to this method as
54
+ # symbols.
55
+ #
56
+ # Example:
57
+ #
58
+ # set_color "Hi!", :red, :on_white, :bold
59
+ #
60
+ # The available colors are:
61
+ #
62
+ # :bold
63
+ # :black
64
+ # :red
65
+ # :green
66
+ # :yellow
67
+ # :blue
68
+ # :magenta
69
+ # :cyan
70
+ # :white
71
+ # :on_black
72
+ # :on_red
73
+ # :on_green
74
+ # :on_yellow
75
+ # :on_blue
76
+ # :on_magenta
77
+ # :on_cyan
78
+ # :on_white
79
+ def set_color(string, *colors)
80
+ if colors.all? { |color| color.is_a?(Symbol) || color.is_a?(String) }
81
+ ansi_colors = colors.map { |color| lookup_color(color) }
82
+ "#{ansi_colors.join}#{string}#{CLEAR}"
83
+ else
84
+ # The old API was `set_color(color, bold=boolean)`. We
85
+ # continue to support the old API because you should never
86
+ # break old APIs unnecessarily :P
87
+ foreground, bold = colors
88
+ foreground = self.class.const_get(foreground.to_s.upcase) if foreground.is_a?(Symbol)
89
+
90
+ bold = bold ? BOLD : ""
91
+ "#{bold}#{foreground}#{string}#{CLEAR}"
92
+ end
57
93
  end
58
94
 
59
95
  protected
@@ -0,0 +1,123 @@
1
+ require 'thor/shell/basic'
2
+
3
+ class Thor
4
+ module Shell
5
+ # Inherit from Thor::Shell::Basic and add set_color behavior. Check
6
+ # Thor::Shell::Basic to see all available methods.
7
+ #
8
+ class HTML < Basic
9
+ # The start of an HTML bold sequence.
10
+ BOLD = "font-weight: bold"
11
+
12
+ # Set the terminal's foreground HTML color to black.
13
+ BLACK = 'color: black'
14
+ # Set the terminal's foreground HTML color to red.
15
+ RED = 'color: red'
16
+ # Set the terminal's foreground HTML color to green.
17
+ GREEN = 'color: green'
18
+ # Set the terminal's foreground HTML color to yellow.
19
+ YELLOW = 'color: yellow'
20
+ # Set the terminal's foreground HTML color to blue.
21
+ BLUE = 'color: blue'
22
+ # Set the terminal's foreground HTML color to magenta.
23
+ MAGENTA = 'color: magenta'
24
+ # Set the terminal's foreground HTML color to cyan.
25
+ CYAN = 'color: cyan'
26
+ # Set the terminal's foreground HTML color to white.
27
+ WHITE = 'color: white'
28
+
29
+ # Set the terminal's background HTML color to black.
30
+ ON_BLACK = 'background-color: black'
31
+ # Set the terminal's background HTML color to red.
32
+ ON_RED = 'background-color: red'
33
+ # Set the terminal's background HTML color to green.
34
+ ON_GREEN = 'background-color: green'
35
+ # Set the terminal's background HTML color to yellow.
36
+ ON_YELLOW = 'background-color: yellow'
37
+ # Set the terminal's background HTML color to blue.
38
+ ON_BLUE = 'background-color: blue'
39
+ # Set the terminal's background HTML color to magenta.
40
+ ON_MAGENTA = 'background-color: magenta'
41
+ # Set the terminal's background HTML color to cyan.
42
+ ON_CYAN = 'background-color: cyan'
43
+ # Set the terminal's background HTML color to white.
44
+ ON_WHITE = 'background-color: white'
45
+
46
+ # Set color by using a string or one of the defined constants. If a third
47
+ # option is set to true, it also adds bold to the string. This is based
48
+ # on Highline implementation and it automatically appends CLEAR to the end
49
+ # of the returned String.
50
+ #
51
+ def set_color(string, *colors)
52
+ if colors.all? { |color| color.is_a?(Symbol) || color.is_a?(String) }
53
+ html_colors = colors.map { |color| lookup_color(color) }
54
+ "<span style=\"#{html_colors.join("; ")};\">#{string}</span>"
55
+ else
56
+ color, bold = colors
57
+ html_color = self.class.const_get(color.to_s.upcase) if color.is_a?(Symbol)
58
+ styles = [html_color]
59
+ styles << BOLD if bold
60
+ "<span style=\"#{styles.join("; ")};\">#{string}</span>"
61
+ end
62
+ end
63
+
64
+ # Ask something to the user and receives a response.
65
+ #
66
+ # ==== Example
67
+ # ask("What is your name?")
68
+ #
69
+ # TODO: Implement #ask for Thor::Shell::HTML
70
+ def ask(statement, color=nil)
71
+ raise NotImplementedError, "Implement #ask for Thor::Shell::HTML"
72
+ end
73
+
74
+ protected
75
+
76
+ # Overwrite show_diff to show diff with colors if Diff::LCS is
77
+ # available.
78
+ #
79
+ def show_diff(destination, content) #:nodoc:
80
+ if diff_lcs_loaded? && ENV['THOR_DIFF'].nil? && ENV['RAILS_DIFF'].nil?
81
+ actual = File.binread(destination).to_s.split("\n")
82
+ content = content.to_s.split("\n")
83
+
84
+ Diff::LCS.sdiff(actual, content).each do |diff|
85
+ output_diff_line(diff)
86
+ end
87
+ else
88
+ super
89
+ end
90
+ end
91
+
92
+ def output_diff_line(diff) #:nodoc:
93
+ case diff.action
94
+ when '-'
95
+ say "- #{diff.old_element.chomp}", :red, true
96
+ when '+'
97
+ say "+ #{diff.new_element.chomp}", :green, true
98
+ when '!'
99
+ say "- #{diff.old_element.chomp}", :red, true
100
+ say "+ #{diff.new_element.chomp}", :green, true
101
+ else
102
+ say " #{diff.old_element.chomp}", nil, true
103
+ end
104
+ end
105
+
106
+ # Check if Diff::LCS is loaded. If it is, use it to create pretty output
107
+ # for diff.
108
+ #
109
+ def diff_lcs_loaded? #:nodoc:
110
+ return true if defined?(Diff::LCS)
111
+ return @diff_lcs_loaded unless @diff_lcs_loaded.nil?
112
+
113
+ @diff_lcs_loaded = begin
114
+ require 'diff/lcs'
115
+ true
116
+ rescue LoadError
117
+ false
118
+ end
119
+ end
120
+
121
+ end
122
+ end
123
+ end
@@ -1,24 +1,9 @@
1
1
  class Thor
2
- class Task < Struct.new(:name, :description, :usage, :options)
2
+ class Task < Struct.new(:name, :description, :long_description, :usage, :options)
3
3
  FILE_REGEXP = /^#{Regexp.escape(File.dirname(__FILE__))}/
4
4
 
5
- # A dynamic task that handles method missing scenarios.
6
- class Dynamic < Task
7
- def initialize(name, options=nil)
8
- super(name.to_s, "A dynamically-generated task", name.to_s, options)
9
- end
10
-
11
- def run(instance, args=[])
12
- if (instance.methods & [name.to_s, name.to_sym]).empty?
13
- super
14
- else
15
- instance.class.handle_no_task_error(name)
16
- end
17
- end
18
- end
19
-
20
- def initialize(name, description, usage, options=nil)
21
- super(name.to_s, description, usage, options || {})
5
+ def initialize(name, description, long_description, usage, options=nil)
6
+ super(name.to_s, description, long_description, usage, options || {})
22
7
  end
23
8
 
24
9
  def initialize_copy(other) #:nodoc:
@@ -26,30 +11,43 @@ class Thor
26
11
  self.options = other.options.dup if other.options
27
12
  end
28
13
 
14
+ def hidden?
15
+ false
16
+ end
17
+
29
18
  # By default, a task invokes a method in the thor class. You can change this
30
19
  # implementation to create custom tasks.
31
20
  def run(instance, args=[])
32
- public_method?(instance) ?
33
- instance.send(name, *args) : instance.class.handle_no_task_error(name)
21
+ arity = nil
22
+
23
+ if private_method?(instance)
24
+ instance.class.handle_no_task_error(name)
25
+ elsif public_method?(instance)
26
+ arity = instance.method(name).arity
27
+ instance.send(name, *args)
28
+ elsif local_method?(instance, :method_missing)
29
+ instance.send(:method_missing, name.to_sym, *args)
30
+ else
31
+ instance.class.handle_no_task_error(name)
32
+ end
34
33
  rescue ArgumentError => e
35
34
  handle_argument_error?(instance, e, caller) ?
36
- instance.class.handle_argument_error(self, e) : (raise e)
35
+ instance.class.handle_argument_error(self, e, arity) : (raise e)
37
36
  rescue NoMethodError => e
38
37
  handle_no_method_error?(instance, e, caller) ?
39
38
  instance.class.handle_no_task_error(name) : (raise e)
40
39
  end
41
40
 
42
- # Returns the formatted usage by injecting given required arguments
41
+ # Returns the formatted usage by injecting given required arguments
43
42
  # and required options into the given usage.
44
- def formatted_usage(klass, namespace=true)
45
- namespace = klass.namespace unless namespace == false
46
-
47
- # Add namespace
48
- formatted = if namespace
49
- "#{namespace.gsub(/^(default|thor:runner:)/,'')}:"
50
- else
51
- ""
43
+ def formatted_usage(klass, namespace = true, subcommand = false)
44
+ if namespace
45
+ namespace = klass.namespace
46
+ formatted = "#{namespace.gsub(/^(default)/,'')}:"
52
47
  end
48
+ formatted = "#{klass.namespace.split(':').last} " if subcommand
49
+
50
+ formatted ||= ""
53
51
 
54
52
  # Add usage with required arguments
55
53
  formatted << if klass && !klass.arguments.empty?
@@ -67,36 +65,68 @@ class Thor
67
65
  formatted.strip
68
66
  end
69
67
 
70
- protected
68
+ protected
71
69
 
72
- def not_debugging?(instance)
73
- !(instance.class.respond_to?(:debugging) && instance.class.debugging)
74
- end
70
+ def not_debugging?(instance)
71
+ !(instance.class.respond_to?(:debugging) && instance.class.debugging)
72
+ end
75
73
 
76
- def required_options
77
- @required_options ||= options.map{ |_, o| o.usage if o.required? }.compact.sort.join(" ")
78
- end
74
+ def required_options
75
+ @required_options ||= options.map{ |_, o| o.usage if o.required? }.compact.sort.join(" ")
76
+ end
79
77
 
80
- # Given a target, checks if this class name is not a private/protected method.
81
- def public_method?(instance) #:nodoc:
82
- collection = instance.private_methods + instance.protected_methods
83
- (collection & [name.to_s, name.to_sym]).empty?
84
- end
78
+ # Given a target, checks if this class name is a public method.
79
+ def public_method?(instance) #:nodoc:
80
+ !(instance.public_methods & [name.to_s, name.to_sym]).empty?
81
+ end
85
82
 
86
- def sans_backtrace(backtrace, caller) #:nodoc:
87
- saned = backtrace.reject { |frame| frame =~ FILE_REGEXP }
88
- saned -= caller
89
- end
83
+ def private_method?(instance)
84
+ !(instance.private_methods & [name.to_s, name.to_sym]).empty?
85
+ end
90
86
 
91
- def handle_argument_error?(instance, error, caller)
92
- not_debugging?(instance) && error.message =~ /wrong number of arguments/ &&
93
- sans_backtrace(error.backtrace, caller).empty?
94
- end
87
+ def local_method?(instance, name)
88
+ methods = instance.public_methods(false) + instance.private_methods(false) + instance.protected_methods(false)
89
+ !(methods & [name.to_s, name.to_sym]).empty?
90
+ end
91
+
92
+ def sans_backtrace(backtrace, caller) #:nodoc:
93
+ saned = backtrace.reject { |frame| frame =~ FILE_REGEXP || (frame =~ /\.java:/ && RUBY_PLATFORM =~ /java/) }
94
+ saned -= caller
95
+ end
95
96
 
96
- def handle_no_method_error?(instance, error, caller)
97
- not_debugging?(instance) &&
98
- error.message =~ /^undefined method `#{name}' for #{Regexp.escape(instance.to_s)}$/
97
+ def handle_argument_error?(instance, error, caller)
98
+ not_debugging?(instance) && error.message =~ /wrong number of arguments/ && begin
99
+ saned = sans_backtrace(error.backtrace, caller)
100
+ # Ruby 1.9 always include the called method in the backtrace
101
+ saned.empty? || (saned.size == 1 && RUBY_VERSION >= "1.9")
99
102
  end
103
+ end
104
+
105
+ def handle_no_method_error?(instance, error, caller)
106
+ not_debugging?(instance) &&
107
+ error.message =~ /^undefined method `#{name}' for #{Regexp.escape(instance.to_s)}$/
108
+ end
109
+ end
100
110
 
111
+ # A task that is hidden in help messages but still invocable.
112
+ class HiddenTask < Task
113
+ def hidden?
114
+ true
115
+ end
116
+ end
117
+
118
+ # A dynamic task that handles method missing scenarios.
119
+ class DynamicTask < Task
120
+ def initialize(name, options=nil)
121
+ super(name.to_s, "A dynamically-generated task", name.to_s, name.to_s, options)
122
+ end
123
+
124
+ def run(instance, args=[])
125
+ if (instance.methods & [name.to_s, name.to_sym]).empty?
126
+ super
127
+ else
128
+ instance.class.handle_no_task_error(name)
129
+ end
130
+ end
101
131
  end
102
132
  end
@@ -8,11 +8,11 @@ class Thor
8
8
  #
9
9
  # 1) Methods to convert thor namespaces to constants and vice-versa.
10
10
  #
11
- # Thor::Utils.namespace_from_thor_class(Foo::Bar::Baz) #=> "foo:bar:baz"
11
+ # Thor::Util.namespace_from_thor_class(Foo::Bar::Baz) #=> "foo:bar:baz"
12
12
  #
13
13
  # 2) Loading thor files and sandboxing:
14
14
  #
15
- # Thor::Utils.load_thorfile("~/.thor/foo")
15
+ # Thor::Util.load_thorfile("~/.thor/foo")
16
16
  #
17
17
  module Util
18
18
 
@@ -128,38 +128,37 @@ class Thor
128
128
  # ==== Parameters
129
129
  # namespace<String>
130
130
  #
131
- def self.find_class_and_task_by_namespace(namespace)
132
- if namespace.include?(?:)
131
+ def self.find_class_and_task_by_namespace(namespace, fallback = true)
132
+ if namespace.include?(?:) # look for a namespaced task
133
133
  pieces = namespace.split(":")
134
134
  task = pieces.pop
135
135
  klass = Thor::Util.find_by_namespace(pieces.join(":"))
136
136
  end
137
-
138
- unless klass
137
+ unless klass # look for a Thor::Group with the right name
139
138
  klass, task = Thor::Util.find_by_namespace(namespace), nil
140
139
  end
141
-
142
- return klass, task
143
- end
144
-
145
- # The same as namespace_to_thor_class_and_task!, but raises an error if a klass
146
- # could not be found.
147
- def self.find_class_and_task_by_namespace!(namespace)
148
- klass, task = find_class_and_task_by_namespace(namespace)
149
- raise Error, "Could not find namespace or task #{namespace.inspect}." unless klass
140
+ if !klass && fallback # try a task in the default namespace
141
+ task = namespace
142
+ klass = Thor::Util.find_by_namespace('')
143
+ end
150
144
  return klass, task
151
145
  end
152
146
 
153
147
  # Receives a path and load the thor file in the path. The file is evaluated
154
148
  # inside the sandbox to avoid namespacing conflicts.
155
149
  #
156
- def self.load_thorfile(path, content=nil)
150
+ def self.load_thorfile(path, content=nil, debug=false)
157
151
  content ||= File.binread(path)
158
152
 
159
153
  begin
160
154
  Thor::Sandbox.class_eval(content, path)
161
155
  rescue Exception => e
162
- $stderr.puts "WARNING: unable to load thorfile #{path.inspect}: #{e.message}"
156
+ $stderr.puts("WARNING: unable to load thorfile #{path.inspect}: #{e.message}")
157
+ if debug
158
+ $stderr.puts(*e.backtrace)
159
+ else
160
+ $stderr.puts(e.backtrace.first)
161
+ end
163
162
  end
164
163
  end
165
164
 
@@ -185,7 +184,7 @@ class Thor
185
184
  end
186
185
  end
187
186
 
188
- # Returns the root where thor files are located, dependending on the OS.
187
+ # Returns the root where thor files are located, depending on the OS.
189
188
  #
190
189
  def self.thor_root
191
190
  File.join(user_home, ".thor").gsub(/\\/, '/')
@@ -199,7 +198,7 @@ class Thor
199
198
  # If we don't #gsub the \ character, Dir.glob will fail.
200
199
  #
201
200
  def self.thor_root_glob
202
- files = Dir["#{thor_root}/*"]
201
+ files = Dir["#{escape_globs(thor_root)}/*"]
203
202
 
204
203
  files.map! do |file|
205
204
  File.directory?(file) ? File.join(file, "main.thor") : file
@@ -209,6 +208,7 @@ class Thor
209
208
  # Where to look for Thor files.
210
209
  #
211
210
  def self.globs_for(path)
211
+ path = escape_globs(path)
212
212
  ["#{path}/Thorfile", "#{path}/*.thor", "#{path}/tasks/*.thor", "#{path}/lib/tasks/*.thor"]
213
213
  end
214
214
 
@@ -217,8 +217,27 @@ class Thor
217
217
  #
218
218
  def self.ruby_command
219
219
  @ruby_command ||= begin
220
- ruby = File.join(Config::CONFIG['bindir'], Config::CONFIG['ruby_install_name'])
221
- ruby << Config::CONFIG['EXEEXT']
220
+ ruby_name = RbConfig::CONFIG['ruby_install_name']
221
+ ruby = File.join(RbConfig::CONFIG['bindir'], ruby_name)
222
+ ruby << RbConfig::CONFIG['EXEEXT']
223
+
224
+ # avoid using different name than ruby (on platforms supporting links)
225
+ if ruby_name != 'ruby' && File.respond_to?(:readlink)
226
+ begin
227
+ alternate_ruby = File.join(RbConfig::CONFIG['bindir'], 'ruby')
228
+ alternate_ruby << RbConfig::CONFIG['EXEEXT']
229
+
230
+ # ruby is a symlink
231
+ if File.symlink? alternate_ruby
232
+ linked_ruby = File.readlink alternate_ruby
233
+
234
+ # symlink points to 'ruby_install_name'
235
+ ruby = alternate_ruby if linked_ruby == ruby_name || linked_ruby == ruby
236
+ end
237
+ rescue NotImplementedError
238
+ # just ignore on windows
239
+ end
240
+ end
222
241
 
223
242
  # escape string in case path to ruby executable contain spaces.
224
243
  ruby.sub!(/.*\s.*/m, '"\&"')
@@ -226,5 +245,22 @@ class Thor
226
245
  end
227
246
  end
228
247
 
248
+ # Returns a string that has had any glob characters escaped.
249
+ # The glob characters are `* ? { } [ ]`.
250
+ #
251
+ # ==== Examples
252
+ #
253
+ # Thor::Util.escape_globs('[apps]') # => '\[apps\]'
254
+ #
255
+ # ==== Parameters
256
+ # String
257
+ #
258
+ # ==== Returns
259
+ # String
260
+ #
261
+ def self.escape_globs(path)
262
+ path.to_s.gsub(/[*?{}\[\]]/, '\\\\\\&')
263
+ end
264
+
229
265
  end
230
266
  end