bundler_package_git 1.1.pre.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 (149) hide show
  1. data/.gitignore +22 -0
  2. data/.rvmrc +1 -0
  3. data/CHANGELOG.md +659 -0
  4. data/ISSUES.md +47 -0
  5. data/LICENSE +23 -0
  6. data/README.md +29 -0
  7. data/Rakefile +167 -0
  8. data/UPGRADING.md +103 -0
  9. data/bin/bundle +22 -0
  10. data/bundler.gemspec +30 -0
  11. data/lib/bundler.rb +283 -0
  12. data/lib/bundler/capistrano.rb +11 -0
  13. data/lib/bundler/cli.rb +490 -0
  14. data/lib/bundler/definition.rb +429 -0
  15. data/lib/bundler/dependency.rb +130 -0
  16. data/lib/bundler/deployment.rb +53 -0
  17. data/lib/bundler/dsl.rb +243 -0
  18. data/lib/bundler/environment.rb +47 -0
  19. data/lib/bundler/fetcher.rb +101 -0
  20. data/lib/bundler/gem_helper.rb +146 -0
  21. data/lib/bundler/graph.rb +130 -0
  22. data/lib/bundler/index.rb +131 -0
  23. data/lib/bundler/installer.rb +117 -0
  24. data/lib/bundler/lazy_specification.rb +71 -0
  25. data/lib/bundler/lockfile_parser.rb +108 -0
  26. data/lib/bundler/remote_specification.rb +57 -0
  27. data/lib/bundler/resolver.rb +470 -0
  28. data/lib/bundler/rubygems_ext.rb +226 -0
  29. data/lib/bundler/runtime.rb +201 -0
  30. data/lib/bundler/settings.rb +117 -0
  31. data/lib/bundler/setup.rb +16 -0
  32. data/lib/bundler/shared_helpers.rb +167 -0
  33. data/lib/bundler/source.rb +675 -0
  34. data/lib/bundler/spec_set.rb +134 -0
  35. data/lib/bundler/templates/Executable +16 -0
  36. data/lib/bundler/templates/Gemfile +4 -0
  37. data/lib/bundler/templates/newgem/Gemfile.tt +4 -0
  38. data/lib/bundler/templates/newgem/Rakefile.tt +2 -0
  39. data/lib/bundler/templates/newgem/bin/newgem.tt +3 -0
  40. data/lib/bundler/templates/newgem/gitignore.tt +4 -0
  41. data/lib/bundler/templates/newgem/lib/newgem.rb.tt +7 -0
  42. data/lib/bundler/templates/newgem/lib/newgem/version.rb.tt +7 -0
  43. data/lib/bundler/templates/newgem/newgem.gemspec.tt +21 -0
  44. data/lib/bundler/ui.rb +73 -0
  45. data/lib/bundler/vendor/net/http/faster.rb +27 -0
  46. data/lib/bundler/vendor/net/http/persistent.rb +464 -0
  47. data/lib/bundler/vendor/thor.rb +319 -0
  48. data/lib/bundler/vendor/thor/actions.rb +297 -0
  49. data/lib/bundler/vendor/thor/actions/create_file.rb +105 -0
  50. data/lib/bundler/vendor/thor/actions/directory.rb +93 -0
  51. data/lib/bundler/vendor/thor/actions/empty_directory.rb +134 -0
  52. data/lib/bundler/vendor/thor/actions/file_manipulation.rb +229 -0
  53. data/lib/bundler/vendor/thor/actions/inject_into_file.rb +104 -0
  54. data/lib/bundler/vendor/thor/base.rb +556 -0
  55. data/lib/bundler/vendor/thor/core_ext/file_binary_read.rb +9 -0
  56. data/lib/bundler/vendor/thor/core_ext/hash_with_indifferent_access.rb +75 -0
  57. data/lib/bundler/vendor/thor/core_ext/ordered_hash.rb +100 -0
  58. data/lib/bundler/vendor/thor/error.rb +30 -0
  59. data/lib/bundler/vendor/thor/invocation.rb +168 -0
  60. data/lib/bundler/vendor/thor/parser.rb +4 -0
  61. data/lib/bundler/vendor/thor/parser/argument.rb +67 -0
  62. data/lib/bundler/vendor/thor/parser/arguments.rb +161 -0
  63. data/lib/bundler/vendor/thor/parser/option.rb +120 -0
  64. data/lib/bundler/vendor/thor/parser/options.rb +174 -0
  65. data/lib/bundler/vendor/thor/shell.rb +88 -0
  66. data/lib/bundler/vendor/thor/shell/basic.rb +275 -0
  67. data/lib/bundler/vendor/thor/shell/color.rb +108 -0
  68. data/lib/bundler/vendor/thor/shell/html.rb +121 -0
  69. data/lib/bundler/vendor/thor/task.rb +114 -0
  70. data/lib/bundler/vendor/thor/util.rb +229 -0
  71. data/lib/bundler/vendor/thor/version.rb +3 -0
  72. data/lib/bundler/version.rb +6 -0
  73. data/lib/bundler/vlad.rb +9 -0
  74. data/man/bundle-config.ronn +90 -0
  75. data/man/bundle-exec.ronn +111 -0
  76. data/man/bundle-install.ronn +314 -0
  77. data/man/bundle-package.ronn +59 -0
  78. data/man/bundle-update.ronn +176 -0
  79. data/man/bundle.ronn +80 -0
  80. data/man/gemfile.5.ronn +279 -0
  81. data/man/index.txt +6 -0
  82. data/spec/cache/gems_spec.rb +219 -0
  83. data/spec/cache/git_spec.rb +9 -0
  84. data/spec/cache/path_spec.rb +27 -0
  85. data/spec/cache/platform_spec.rb +57 -0
  86. data/spec/install/deploy_spec.rb +197 -0
  87. data/spec/install/deprecated_spec.rb +37 -0
  88. data/spec/install/gems/c_ext_spec.rb +48 -0
  89. data/spec/install/gems/dependency_api_spec.rb +85 -0
  90. data/spec/install/gems/env_spec.rb +107 -0
  91. data/spec/install/gems/flex_spec.rb +313 -0
  92. data/spec/install/gems/groups_spec.rb +245 -0
  93. data/spec/install/gems/packed_spec.rb +84 -0
  94. data/spec/install/gems/platform_spec.rb +208 -0
  95. data/spec/install/gems/resolving_spec.rb +72 -0
  96. data/spec/install/gems/simple_case_spec.rb +715 -0
  97. data/spec/install/gems/standalone_spec.rb +162 -0
  98. data/spec/install/gems/sudo_spec.rb +73 -0
  99. data/spec/install/gems/win32_spec.rb +26 -0
  100. data/spec/install/gemspec_spec.rb +108 -0
  101. data/spec/install/git_spec.rb +571 -0
  102. data/spec/install/invalid_spec.rb +17 -0
  103. data/spec/install/path_spec.rb +353 -0
  104. data/spec/install/upgrade_spec.rb +26 -0
  105. data/spec/lock/git_spec.rb +35 -0
  106. data/spec/lock/lockfile_spec.rb +683 -0
  107. data/spec/other/check_spec.rb +221 -0
  108. data/spec/other/clean_spec.rb +202 -0
  109. data/spec/other/config_spec.rb +40 -0
  110. data/spec/other/console_spec.rb +54 -0
  111. data/spec/other/exec_spec.rb +241 -0
  112. data/spec/other/ext_spec.rb +16 -0
  113. data/spec/other/gem_helper_spec.rb +128 -0
  114. data/spec/other/help_spec.rb +38 -0
  115. data/spec/other/init_spec.rb +40 -0
  116. data/spec/other/newgem_spec.rb +24 -0
  117. data/spec/other/open_spec.rb +35 -0
  118. data/spec/other/show_spec.rb +82 -0
  119. data/spec/pack/gems_spec.rb +54 -0
  120. data/spec/quality_spec.rb +58 -0
  121. data/spec/resolver/basic_spec.rb +20 -0
  122. data/spec/resolver/platform_spec.rb +82 -0
  123. data/spec/runtime/executable_spec.rb +110 -0
  124. data/spec/runtime/load_spec.rb +107 -0
  125. data/spec/runtime/platform_spec.rb +90 -0
  126. data/spec/runtime/require_spec.rb +231 -0
  127. data/spec/runtime/setup_spec.rb +688 -0
  128. data/spec/runtime/with_clean_env_spec.rb +15 -0
  129. data/spec/spec_helper.rb +85 -0
  130. data/spec/support/artifice/endpoint.rb +50 -0
  131. data/spec/support/artifice/endpoint_fallback.rb +22 -0
  132. data/spec/support/artifice/endpoint_marshal_fail.rb +11 -0
  133. data/spec/support/artifice/endpoint_redirect.rb +11 -0
  134. data/spec/support/builders.rb +574 -0
  135. data/spec/support/fakeweb/rack-1.0.0.marshal +2 -0
  136. data/spec/support/fakeweb/windows.rb +23 -0
  137. data/spec/support/helpers.rb +246 -0
  138. data/spec/support/indexes.rb +112 -0
  139. data/spec/support/matchers.rb +89 -0
  140. data/spec/support/path.rb +73 -0
  141. data/spec/support/platforms.rb +53 -0
  142. data/spec/support/ruby_ext.rb +20 -0
  143. data/spec/support/rubygems_ext.rb +35 -0
  144. data/spec/support/rubygems_hax/platform.rb +11 -0
  145. data/spec/support/sudo.rb +21 -0
  146. data/spec/update/gems_spec.rb +121 -0
  147. data/spec/update/git_spec.rb +196 -0
  148. data/spec/update/source_spec.rb +51 -0
  149. metadata +294 -0
@@ -0,0 +1,319 @@
1
+ require 'thor/base'
2
+
3
+ class Thor
4
+ class << self
5
+ # Sets the default task when thor is executed without an explicit task to be called.
6
+ #
7
+ # ==== Parameters
8
+ # meth<Symbol>:: name of the defaut task
9
+ #
10
+ def default_task(meth=nil)
11
+ case meth
12
+ when :none
13
+ @default_task = 'help'
14
+ when nil
15
+ @default_task ||= from_superclass(:default_task, 'help')
16
+ else
17
+ @default_task = meth.to_s
18
+ end
19
+ end
20
+
21
+ # Defines the usage and the description of the next task.
22
+ #
23
+ # ==== Parameters
24
+ # usage<String>
25
+ # description<String>
26
+ # options<String>
27
+ #
28
+ def desc(usage, description, options={})
29
+ if options[:for]
30
+ task = find_and_refresh_task(options[:for])
31
+ task.usage = usage if usage
32
+ task.description = description if description
33
+ else
34
+ @usage, @desc, @hide = usage, description, options[:hide] || false
35
+ end
36
+ end
37
+
38
+ # Defines the long description of the next task.
39
+ #
40
+ # ==== Parameters
41
+ # long description<String>
42
+ #
43
+ def long_desc(long_description, options={})
44
+ if options[:for]
45
+ task = find_and_refresh_task(options[:for])
46
+ task.long_description = long_description if long_description
47
+ else
48
+ @long_desc = long_description
49
+ end
50
+ end
51
+
52
+ # Maps an input to a task. If you define:
53
+ #
54
+ # map "-T" => "list"
55
+ #
56
+ # Running:
57
+ #
58
+ # thor -T
59
+ #
60
+ # Will invoke the list task.
61
+ #
62
+ # ==== Parameters
63
+ # Hash[String|Array => Symbol]:: Maps the string or the strings in the array to the given task.
64
+ #
65
+ def map(mappings=nil)
66
+ @map ||= from_superclass(:map, {})
67
+
68
+ if mappings
69
+ mappings.each do |key, value|
70
+ if key.respond_to?(:each)
71
+ key.each {|subkey| @map[subkey] = value}
72
+ else
73
+ @map[key] = value
74
+ end
75
+ end
76
+ end
77
+
78
+ @map
79
+ end
80
+
81
+ # Declares the options for the next task to be declared.
82
+ #
83
+ # ==== Parameters
84
+ # Hash[Symbol => Object]:: The hash key is the name of the option and the value
85
+ # is the type of the option. Can be :string, :array, :hash, :boolean, :numeric
86
+ # or :required (string). If you give a value, the type of the value is used.
87
+ #
88
+ def method_options(options=nil)
89
+ @method_options ||= {}
90
+ build_options(options, @method_options) if options
91
+ @method_options
92
+ end
93
+
94
+ # Adds an option to the set of method options. If :for is given as option,
95
+ # it allows you to change the options from a previous defined task.
96
+ #
97
+ # def previous_task
98
+ # # magic
99
+ # end
100
+ #
101
+ # method_option :foo => :bar, :for => :previous_task
102
+ #
103
+ # def next_task
104
+ # # magic
105
+ # end
106
+ #
107
+ # ==== Parameters
108
+ # name<Symbol>:: The name of the argument.
109
+ # options<Hash>:: Described below.
110
+ #
111
+ # ==== Options
112
+ # :desc - Description for the argument.
113
+ # :required - If the argument is required or not.
114
+ # :default - Default value for this argument. It cannot be required and have default values.
115
+ # :aliases - Aliases for this option.
116
+ # :type - The type of the argument, can be :string, :hash, :array, :numeric or :boolean.
117
+ # :banner - String to show on usage notes.
118
+ #
119
+ def method_option(name, options={})
120
+ scope = if options[:for]
121
+ find_and_refresh_task(options[:for]).options
122
+ else
123
+ method_options
124
+ end
125
+
126
+ build_option(name, options, scope)
127
+ end
128
+
129
+ # Prints help information for the given task.
130
+ #
131
+ # ==== Parameters
132
+ # shell<Thor::Shell>
133
+ # task_name<String>
134
+ #
135
+ def task_help(shell, task_name)
136
+ meth = normalize_task_name(task_name)
137
+ task = all_tasks[meth]
138
+ handle_no_task_error(meth) unless task
139
+
140
+ shell.say "Usage:"
141
+ shell.say " #{banner(task)}"
142
+ shell.say
143
+ class_options_help(shell, nil => task.options.map { |_, o| o })
144
+ if task.long_description
145
+ shell.say "Description:"
146
+ shell.print_wrapped(task.long_description, :ident => 2)
147
+ else
148
+ shell.say task.description
149
+ end
150
+ end
151
+
152
+ # Prints help information for this class.
153
+ #
154
+ # ==== Parameters
155
+ # shell<Thor::Shell>
156
+ #
157
+ def help(shell, subcommand = false)
158
+ list = printable_tasks(true, subcommand)
159
+ Thor::Util.thor_classes_in(self).each do |klass|
160
+ list += klass.printable_tasks(false)
161
+ end
162
+ list.sort!{ |a,b| a[0] <=> b[0] }
163
+
164
+ shell.say "Tasks:"
165
+ shell.print_table(list, :ident => 2, :truncate => true)
166
+ shell.say
167
+ class_options_help(shell)
168
+ end
169
+
170
+ # Returns tasks ready to be printed.
171
+ def printable_tasks(all = true, subcommand = false)
172
+ (all ? all_tasks : tasks).map do |_, task|
173
+ next if task.hidden?
174
+ item = []
175
+ item << banner(task, false, subcommand)
176
+ item << (task.description ? "# #{task.description.gsub(/\s+/m,' ')}" : "")
177
+ item
178
+ end.compact
179
+ end
180
+
181
+ def subcommands
182
+ @subcommands ||= from_superclass(:subcommands, [])
183
+ end
184
+
185
+ def subcommand(subcommand, subcommand_class)
186
+ self.subcommands << subcommand.to_s
187
+ subcommand_class.subcommand_help subcommand
188
+ define_method(subcommand) { |*args| invoke subcommand_class, args }
189
+ end
190
+
191
+ # Extend check unknown options to accept a hash of conditions.
192
+ #
193
+ # === Parameters
194
+ # options<Hash>: A hash containing :only and/or :except keys
195
+ def check_unknown_options!(options={})
196
+ @check_unknown_options ||= Hash.new
197
+ options.each do |key, value|
198
+ if value
199
+ @check_unknown_options[key] = Array(value)
200
+ else
201
+ @check_unknown_options.delete(key)
202
+ end
203
+ end
204
+ @check_unknown_options
205
+ end
206
+
207
+ # Overwrite check_unknown_options? to take subcommands and options into account.
208
+ def check_unknown_options?(config) #:nodoc:
209
+ options = check_unknown_options
210
+ return false unless options
211
+
212
+ task = config[:current_task]
213
+ return true unless task
214
+
215
+ name = task.name
216
+
217
+ if subcommands.include?(name)
218
+ false
219
+ elsif options[:except]
220
+ !options[:except].include?(name.to_sym)
221
+ elsif options[:only]
222
+ options[:only].include?(name.to_sym)
223
+ else
224
+ true
225
+ end
226
+ end
227
+
228
+ protected
229
+
230
+ # The method responsible for dispatching given the args.
231
+ def dispatch(meth, given_args, given_opts, config) #:nodoc:
232
+ meth ||= retrieve_task_name(given_args)
233
+ task = all_tasks[normalize_task_name(meth)]
234
+
235
+ if task
236
+ args, opts = Thor::Options.split(given_args)
237
+ else
238
+ args, opts = given_args, nil
239
+ task = Thor::DynamicTask.new(meth)
240
+ end
241
+
242
+ opts = given_opts || opts || []
243
+ config.merge!(:current_task => task, :task_options => task.options)
244
+
245
+ trailing = args[Range.new(arguments.size, -1)]
246
+ new(args, opts, config).invoke_task(task, trailing || [])
247
+ end
248
+
249
+ # The banner for this class. You can customize it if you are invoking the
250
+ # thor class by another ways which is not the Thor::Runner. It receives
251
+ # the task that is going to be invoked and a boolean which indicates if
252
+ # the namespace should be displayed as arguments.
253
+ #
254
+ def banner(task, namespace = nil, subcommand = false)
255
+ base = File.basename($0).split(" ").first
256
+ "#{base} #{task.formatted_usage(self, $thor_runner, subcommand)}"
257
+ end
258
+
259
+ def baseclass #:nodoc:
260
+ Thor
261
+ end
262
+
263
+ def create_task(meth) #:nodoc:
264
+ if @usage && @desc
265
+ base_class = @hide ? Thor::HiddenTask : Thor::Task
266
+ tasks[meth] = base_class.new(meth, @desc, @long_desc, @usage, method_options)
267
+ @usage, @desc, @long_desc, @method_options, @hide = nil
268
+ true
269
+ elsif self.all_tasks[meth] || meth == "method_missing"
270
+ true
271
+ else
272
+ puts "[WARNING] Attempted to create task #{meth.inspect} without usage or description. " <<
273
+ "Call desc if you want this method to be available as task or declare it inside a " <<
274
+ "no_tasks{} block. Invoked from #{caller[1].inspect}."
275
+ false
276
+ end
277
+ end
278
+
279
+ def initialize_added #:nodoc:
280
+ class_options.merge!(method_options)
281
+ @method_options = nil
282
+ end
283
+
284
+ # Retrieve the task name from given args.
285
+ def retrieve_task_name(args) #:nodoc:
286
+ meth = args.first.to_s unless args.empty?
287
+
288
+ if meth && (map[meth] || meth !~ /^\-/)
289
+ args.shift
290
+ else
291
+ nil
292
+ end
293
+ end
294
+
295
+ # Receives a task name (can be nil), and try to get a map from it.
296
+ # If a map can't be found use the sent name or the default task.
297
+ def normalize_task_name(meth) #:nodoc:
298
+ meth = map[meth.to_s] || meth || default_task
299
+ meth.to_s.gsub('-','_') # treat foo-bar > foo_bar
300
+ end
301
+
302
+ def subcommand_help(cmd)
303
+ desc "help [COMMAND]", "Describe subcommands or one specific subcommand"
304
+ class_eval <<-RUBY
305
+ def help(task = nil, subcommand = true); super; end
306
+ RUBY
307
+ end
308
+
309
+ end
310
+
311
+ include Thor::Base
312
+
313
+ map HELP_MAPPINGS => :help
314
+
315
+ desc "help [TASK]", "Describe available tasks or one specific task"
316
+ def help(task = nil, subcommand = false)
317
+ task ? self.class.task_help(shell, task) : self.class.help(shell, subcommand)
318
+ end
319
+ end
@@ -0,0 +1,297 @@
1
+ require 'fileutils'
2
+ require 'uri'
3
+ require 'thor/core_ext/file_binary_read'
4
+
5
+ Dir[File.join(File.dirname(__FILE__), "actions", "*.rb")].each do |action|
6
+ require action
7
+ end
8
+
9
+ class Thor
10
+ module Actions
11
+ attr_accessor :behavior
12
+
13
+ def self.included(base) #:nodoc:
14
+ base.extend ClassMethods
15
+ end
16
+
17
+ module ClassMethods
18
+ # Hold source paths for one Thor instance. source_paths_for_search is the
19
+ # method responsible to gather source_paths from this current class,
20
+ # inherited paths and the source root.
21
+ #
22
+ def source_paths
23
+ @_source_paths ||= []
24
+ end
25
+
26
+ # Stores and return the source root for this class
27
+ def source_root(path=nil)
28
+ @_source_root = path if path
29
+ @_source_root
30
+ end
31
+
32
+ # Returns the source paths in the following order:
33
+ #
34
+ # 1) This class source paths
35
+ # 2) Source root
36
+ # 3) Parents source paths
37
+ #
38
+ def source_paths_for_search
39
+ paths = []
40
+ paths += self.source_paths
41
+ paths << self.source_root if self.source_root
42
+ paths += from_superclass(:source_paths, [])
43
+ paths
44
+ end
45
+
46
+ # Add runtime options that help actions execution.
47
+ #
48
+ def add_runtime_options!
49
+ class_option :force, :type => :boolean, :aliases => "-f", :group => :runtime,
50
+ :desc => "Overwrite files that already exist"
51
+
52
+ class_option :pretend, :type => :boolean, :aliases => "-p", :group => :runtime,
53
+ :desc => "Run but do not make any changes"
54
+
55
+ class_option :quiet, :type => :boolean, :aliases => "-q", :group => :runtime,
56
+ :desc => "Supress status output"
57
+
58
+ class_option :skip, :type => :boolean, :aliases => "-s", :group => :runtime,
59
+ :desc => "Skip files that already exist"
60
+ end
61
+ end
62
+
63
+ # Extends initializer to add more configuration options.
64
+ #
65
+ # ==== Configuration
66
+ # behavior<Symbol>:: The actions default behavior. Can be :invoke or :revoke.
67
+ # It also accepts :force, :skip and :pretend to set the behavior
68
+ # and the respective option.
69
+ #
70
+ # destination_root<String>:: The root directory needed for some actions.
71
+ #
72
+ def initialize(args=[], options={}, config={})
73
+ self.behavior = case config[:behavior].to_s
74
+ when "force", "skip"
75
+ _cleanup_options_and_set(options, config[:behavior])
76
+ :invoke
77
+ when "revoke"
78
+ :revoke
79
+ else
80
+ :invoke
81
+ end
82
+
83
+ super
84
+ self.destination_root = config[:destination_root]
85
+ end
86
+
87
+ # Wraps an action object and call it accordingly to the thor class behavior.
88
+ #
89
+ def action(instance) #:nodoc:
90
+ if behavior == :revoke
91
+ instance.revoke!
92
+ else
93
+ instance.invoke!
94
+ end
95
+ end
96
+
97
+ # Returns the root for this thor class (also aliased as destination root).
98
+ #
99
+ def destination_root
100
+ @destination_stack.last
101
+ end
102
+
103
+ # Sets the root for this thor class. Relatives path are added to the
104
+ # directory where the script was invoked and expanded.
105
+ #
106
+ def destination_root=(root)
107
+ @destination_stack ||= []
108
+ @destination_stack[0] = File.expand_path(root || '')
109
+ end
110
+
111
+ # Returns the given path relative to the absolute root (ie, root where
112
+ # the script started).
113
+ #
114
+ def relative_to_original_destination_root(path, remove_dot=true)
115
+ path = path.gsub(@destination_stack[0], '.')
116
+ remove_dot ? (path[2..-1] || '') : path
117
+ end
118
+
119
+ # Holds source paths in instance so they can be manipulated.
120
+ #
121
+ def source_paths
122
+ @source_paths ||= self.class.source_paths_for_search
123
+ end
124
+
125
+ # Receives a file or directory and search for it in the source paths.
126
+ #
127
+ def find_in_source_paths(file)
128
+ relative_root = relative_to_original_destination_root(destination_root, false)
129
+
130
+ source_paths.each do |source|
131
+ source_file = File.expand_path(file, File.join(source, relative_root))
132
+ return source_file if File.exists?(source_file)
133
+ end
134
+
135
+ message = "Could not find #{file.inspect} in any of your source paths. "
136
+
137
+ unless self.class.source_root
138
+ message << "Please invoke #{self.class.name}.source_root(PATH) with the PATH containing your templates. "
139
+ end
140
+
141
+ if source_paths.empty?
142
+ message << "Currently you have no source paths."
143
+ else
144
+ message << "Your current source paths are: \n#{source_paths.join("\n")}"
145
+ end
146
+
147
+ raise Error, message
148
+ end
149
+
150
+ # Do something in the root or on a provided subfolder. If a relative path
151
+ # is given it's referenced from the current root. The full path is yielded
152
+ # to the block you provide. The path is set back to the previous path when
153
+ # the method exits.
154
+ #
155
+ # ==== Parameters
156
+ # dir<String>:: the directory to move to.
157
+ # config<Hash>:: give :verbose => true to log and use padding.
158
+ #
159
+ def inside(dir='', config={}, &block)
160
+ verbose = config.fetch(:verbose, false)
161
+
162
+ say_status :inside, dir, verbose
163
+ shell.padding += 1 if verbose
164
+ @destination_stack.push File.expand_path(dir, destination_root)
165
+
166
+ FileUtils.mkdir_p(destination_root) unless File.exist?(destination_root)
167
+ FileUtils.cd(destination_root) { block.arity == 1 ? yield(destination_root) : yield }
168
+
169
+ @destination_stack.pop
170
+ shell.padding -= 1 if verbose
171
+ end
172
+
173
+ # Goes to the root and execute the given block.
174
+ #
175
+ def in_root
176
+ inside(@destination_stack.first) { yield }
177
+ end
178
+
179
+ # Loads an external file and execute it in the instance binding.
180
+ #
181
+ # ==== Parameters
182
+ # path<String>:: The path to the file to execute. Can be a web address or
183
+ # a relative path from the source root.
184
+ #
185
+ # ==== Examples
186
+ #
187
+ # apply "http://gist.github.com/103208"
188
+ #
189
+ # apply "recipes/jquery.rb"
190
+ #
191
+ def apply(path, config={})
192
+ verbose = config.fetch(:verbose, true)
193
+ is_uri = path =~ /^https?\:\/\//
194
+ path = find_in_source_paths(path) unless is_uri
195
+
196
+ say_status :apply, path, verbose
197
+ shell.padding += 1 if verbose
198
+
199
+ if is_uri
200
+ contents = open(path, "Accept" => "application/x-thor-template") {|io| io.read }
201
+ else
202
+ contents = open(path) {|io| io.read }
203
+ end
204
+
205
+ instance_eval(contents, path)
206
+ shell.padding -= 1 if verbose
207
+ end
208
+
209
+ # Executes a command returning the contents of the command.
210
+ #
211
+ # ==== Parameters
212
+ # command<String>:: the command to be executed.
213
+ # config<Hash>:: give :verbose => false to not log the status. Specify :with
214
+ # to append an executable to command executation.
215
+ #
216
+ # ==== Example
217
+ #
218
+ # inside('vendor') do
219
+ # run('ln -s ~/edge rails')
220
+ # end
221
+ #
222
+ def run(command, config={})
223
+ return unless behavior == :invoke
224
+
225
+ destination = relative_to_original_destination_root(destination_root, false)
226
+ desc = "#{command} from #{destination.inspect}"
227
+
228
+ if config[:with]
229
+ desc = "#{File.basename(config[:with].to_s)} #{desc}"
230
+ command = "#{config[:with]} #{command}"
231
+ end
232
+
233
+ say_status :run, desc, config.fetch(:verbose, true)
234
+ `#{command}` unless options[:pretend]
235
+ end
236
+
237
+ # Executes a ruby script (taking into account WIN32 platform quirks).
238
+ #
239
+ # ==== Parameters
240
+ # command<String>:: the command to be executed.
241
+ # config<Hash>:: give :verbose => false to not log the status.
242
+ #
243
+ def run_ruby_script(command, config={})
244
+ return unless behavior == :invoke
245
+ run command, config.merge(:with => Thor::Util.ruby_command)
246
+ end
247
+
248
+ # Run a thor command. A hash of options can be given and it's converted to
249
+ # switches.
250
+ #
251
+ # ==== Parameters
252
+ # task<String>:: the task to be invoked
253
+ # args<Array>:: arguments to the task
254
+ # config<Hash>:: give :verbose => false to not log the status. Other options
255
+ # are given as parameter to Thor.
256
+ #
257
+ # ==== Examples
258
+ #
259
+ # thor :install, "http://gist.github.com/103208"
260
+ # #=> thor install http://gist.github.com/103208
261
+ #
262
+ # thor :list, :all => true, :substring => 'rails'
263
+ # #=> thor list --all --substring=rails
264
+ #
265
+ def thor(task, *args)
266
+ config = args.last.is_a?(Hash) ? args.pop : {}
267
+ verbose = config.key?(:verbose) ? config.delete(:verbose) : true
268
+ pretend = config.key?(:pretend) ? config.delete(:pretend) : false
269
+
270
+ args.unshift task
271
+ args.push Thor::Options.to_switches(config)
272
+ command = args.join(' ').strip
273
+
274
+ run command, :with => :thor, :verbose => verbose, :pretend => pretend
275
+ end
276
+
277
+ protected
278
+
279
+ # Allow current root to be shared between invocations.
280
+ #
281
+ def _shared_configuration #:nodoc:
282
+ super.merge!(:destination_root => self.destination_root)
283
+ end
284
+
285
+ def _cleanup_options_and_set(options, key) #:nodoc:
286
+ case options
287
+ when Array
288
+ %w(--force -f --skip -s).each { |i| options.delete(i) }
289
+ options << "--#{key}"
290
+ when Hash
291
+ [:force, :skip, "force", "skip"].each { |i| options.delete(i) }
292
+ options.merge!(key => true)
293
+ end
294
+ end
295
+
296
+ end
297
+ end