engineyard-serverside 2.0.0 → 2.0.1

Sign up to get free protection for your applications and to get access to all the features.
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