sprout 0.5.29 → 0.7.153

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of sprout might be problematic. Click here for more details.

Files changed (48) hide show
  1. data/{MIT-LICENSE.txt → MIT-LICENSE} +0 -0
  2. data/TODO +12 -0
  3. data/bin/sprout +83 -140
  4. data/doc/Bundle +14 -0
  5. data/doc/Generator +35 -0
  6. data/doc/Library +63 -0
  7. data/doc/Task +21 -0
  8. data/doc/Tool +20 -0
  9. data/lib/platform.rb +2 -3
  10. data/lib/progress_bar.rb +39 -23
  11. data/lib/sprout/builder.rb +35 -0
  12. data/lib/sprout/commands/generate.rb +14 -0
  13. data/lib/sprout/general_tasks.rb +5 -0
  14. data/lib/sprout/generator/base_mixins.rb +132 -0
  15. data/lib/sprout/generator/named_base.rb +216 -0
  16. data/lib/sprout/generator.rb +6 -0
  17. data/lib/{log.rb → sprout/log.rb} +2 -2
  18. data/lib/sprout/process_runner.rb +46 -0
  19. data/lib/sprout/project_model.rb +114 -0
  20. data/lib/{remote_file_loader.rb → sprout/remote_file_loader.rb} +63 -36
  21. data/lib/sprout/remote_file_target.rb +96 -0
  22. data/lib/sprout/simple_resolver.rb +88 -0
  23. data/lib/sprout/tasks/gem_wrap_task.rb +192 -0
  24. data/lib/sprout/tasks/library_task.rb +103 -0
  25. data/lib/sprout/tasks/sftp_task.rb +245 -0
  26. data/lib/sprout/tasks/tool_task.rb +541 -0
  27. data/lib/sprout/tasks/zip_task.rb +158 -0
  28. data/lib/{template_resolver.rb → sprout/template_resolver.rb} +10 -7
  29. data/lib/{user.rb → sprout/user.rb} +84 -37
  30. data/lib/sprout/version.rb +4 -3
  31. data/lib/sprout/zip_util.rb +61 -0
  32. data/lib/sprout.rb +377 -285
  33. data/rakefile.rb +93 -119
  34. data/samples/gem_wrap/rakefile.rb +17 -0
  35. metadata +131 -96
  36. data/Manifest.txt +0 -9
  37. data/lib/command.rb +0 -29
  38. data/lib/file_target.rb +0 -8
  39. data/lib/generate.rb +0 -37
  40. data/lib/library.rb +0 -18
  41. data/lib/process_runner.rb +0 -27
  42. data/lib/project.rb +0 -10
  43. data/lib/project_model.rb +0 -59
  44. data/lib/remote_file_target.rb +0 -62
  45. data/lib/task.rb +0 -20
  46. data/lib/template.rb +0 -37
  47. data/lib/tool.rb +0 -18
  48. data/setup.rb +0 -1585
data/lib/sprout.rb CHANGED
@@ -1,278 +1,366 @@
1
- $:.push(File.dirname(__FILE__))
2
1
  require 'rubygems'
3
- require 'rake/clean'
4
- require 'rake/tasklib'
5
- require 'yaml'
6
- require 'log'
7
- require 'erb'
8
- require 'uri'
9
- require 'fileutils'
10
- require 'zip/zipfilesystem'
11
2
  require 'archive/tar/minitar'
12
- require 'platform'
3
+ require 'rake'
4
+ require 'rake/clean'
13
5
 
14
- if(Platform::OS == :win32)
15
- require 'win32/open3'
16
- end
6
+ $:.push(File.dirname(__FILE__))
7
+ require 'progress_bar'
8
+ require 'sprout/log'
9
+ require 'sprout/user'
10
+ require 'sprout/zip_util'
11
+ require 'sprout/remote_file_target'
12
+ require 'sprout/remote_file_loader'
13
+ require 'sprout/simple_resolver'
14
+ require 'sprout/template_resolver'
17
15
 
18
- module PatternPark
19
- class SproutError < StandardError; end
20
- class UsageError < SproutError; end
16
+ require 'rubygems/installer'
17
+ require 'rubygems/source_info_cache'
18
+ require 'rubygems/version'
19
+ require 'rubygems/digest/md5'
21
20
 
22
- class Sprout
23
- attr_accessor :name,
24
- :type,
25
- :render,
26
- :platform,
27
- :base_url,
28
- :dependencies,
29
- :targets,
30
- :config_cache,
31
- :config
21
+ require 'sprout/project_model'
22
+ require 'sprout/builder'
23
+ require 'sprout/version'
24
+ require 'sprout/tasks/tool_task'
25
+ require 'sprout/general_tasks'
26
+
27
+ module Sprout
28
+ class SproutError < StandardError #:nodoc:
29
+ end
32
30
 
33
- @@base_urls = ['http://projectsprouts.googlecode.com/svn/branches/release/sprouts/',
34
- 'http://projectsprouts.googlecode.com/svn/trunk/sprouts/',
35
- 'http://www.projectsprouts.org/sprout/']
31
+ # Sprouts is an open-source, cross-platform project generation and configuration tool
32
+ # for ActionScript 2, ActionScript 3, Adobe AIR and Flex projects. It is built on top
33
+ # of Ruby Gems, Rails Generators and is intended to work on any platform that Ruby runs
34
+ # on including specifically, Windows XP, Windows Vista, Cygwin, OS X and Linux.
35
+ #
36
+ # Sprouts can be separated into some core concepts as follows:
37
+ #
38
+ # ----
39
+ # == Tools
40
+ # :include: ../doc/Tool
41
+ #
42
+ # ----
43
+ # == Libraries
44
+ # :include: ../doc/Library
45
+ #
46
+ # ----
47
+ # == Bundles
48
+ # :include: ../doc/Bundle
49
+ #
50
+ # ----
51
+ # == Generators
52
+ # :include: ../doc/Generator
53
+ #
54
+ # ----
55
+ # == Tasks
56
+ # :include: ../doc/Task
57
+ #
58
+ # ----
59
+ # == Sprout
60
+ #
61
+ # Tools, Libraries and Bundles are distributed as RubyGems and given a specific gem name suffix. For some examples:
62
+ # sprout-flex2sdk-tool
63
+ # sprout-asunit-library
64
+ # sprout-as3-bundle
65
+ #
66
+ # The Sprout application provides shared functionality for each of the different types of Sprouts.
67
+ #
68
+ # The Sprout command line tool primarily provides access to project generators from any sprout bundle that is available
69
+ # to your system, either locally or from the network.
70
+ #
71
+ # When executed from the system path, this class will download and install a named bundle, and execute a +project+
72
+ # generator within that bundle. Following is an example:
73
+ #
74
+ # sprout -n as3 SomeProject
75
+ #
76
+ # The previous command will download and install the latest version of the sprout-as3-bundle gem and initiate the
77
+ # project_generator with a single argument of 'SomeProject'. If the string passed to the -n parameter begins with
78
+ # 'sprout-' it will be unmodified for the lookup. For example:
79
+ #
80
+ # spout -n sprout-as3-bundle SomeProject
81
+ #
82
+ # will not have duplicate strings prepended or suffixed.
83
+ #
84
+ # ----
85
+ # Some additional resources or references:
86
+ #
87
+ # Rake:
88
+ # http://rake.rubyforge.org
89
+ # http://martinfowler.com/articles/rake.html
90
+ #
91
+ # RubyGems:
92
+ # * http://www.rubygems.org
93
+ # * http://www.linuxjournal.com/article/8967
94
+ #
95
+ # Ruby Raven (Mostly Inspiration)
96
+ # * http://raven.rubyforge.org
97
+ #
98
+ class Sprout
36
99
  @@default_rakefiles = ['rakefile', 'Rakefile', 'rakefile.rb', 'Rakefile.rb'].freeze
37
- @@universal = 'universal'
38
- @@update = false
39
- @@project_name = ''
40
- @@config_cache = nil
41
- @@home = nil
42
- @@cache = nil
43
- @@project_path = nil
44
- @@base_url = nil
100
+
101
+ @@name = 'Sprouts'
102
+ @@cache = 'cache'
103
+ @@lib = 'lib'
104
+ @@spec = 'sprout.spec'
105
+ @@home = File.expand_path(File.dirname(File.dirname(__FILE__)))
106
+
107
+ # Execute a generator that is available locally or from the network.
108
+ # * +sprout_name+ A full gem name (ex., sprout-as3-bundle) that contains a generator that matches +generator_name+
109
+ # * +generator_name+ A string like 'project' or 'class' that maps to a generator
110
+ # * +params+ Arbitrary parameters to pass to the generator
111
+ # * +project_path+ Optional parameter. Will default to the nearest folder that contains a valid Rakefile.
112
+ # This Rakefile will usually be loaded by the referenced Generator, and it should have a configured ProjectModel
113
+ # defined in it.
114
+ def self.generate(sprout_name, generator_name, params, project_path=nil)
115
+ Rails::Generator::Base.use_sprout_sources!(sprout_name, project_path)
116
+ generator = Rails::Generator::Base.instance(generator_name, params)
117
+ generator.command(:create).invoke!
118
+ end
45
119
 
46
- ##
47
- # Given a simple string @name, request that sprout
48
- # definition from each location in the location list
49
- # until it's found
50
- #
51
- def Sprout.load(name)
52
- local = File.join(Sprout.config_cache, name)
53
- if(!Sprout.update && File.exists?(local))
54
- return Sprout.load_local(local)
55
- else
56
- @@base_urls.each do |url|
57
- begin
58
- @@base_url = url
59
- loader = RemoteFileLoader.new
60
- loader.get_remote_file(url + name, local)
61
- sprout = Sprout.load_local(local)
62
- # if(sprout.post_install)
63
- # eval(sprout.post_install)
64
- # end
65
- return sprout
66
- rescue OpenURI::HTTPError => e
67
- Log.puts("[WARNING] Sprout not found at: #{url + name}, trying next location")
68
- next
69
- end
70
- raise SproutError.new("\n[ERROR] Sprout could not find '#{name}' definition at any known locations, please check the sprout name and try again.")
120
+ # Remove all installed RubyGems that begin with the string 'sprout' and clear the local sprout cache
121
+ def self.remove_all
122
+ # Set up sudo prefix if not on win machine
123
+ # Only show confirmation if there is at least one installed sprout gem
124
+ confirmation = false
125
+ count = 0
126
+ # For each sprout found, remove it!
127
+ Rails::Generator::GemGeneratorSource.new().each_sprout do |sprout|
128
+ count += 1
129
+ command = "#{get_gem_preamble} uninstall -x -a -i -q #{sprout.name}"
130
+
131
+ if(!confirmation)
132
+ break unless confirmation = remove_gems_confirmation
71
133
  end
134
+ raise ">> Exited with errors: #{$?}" unless system(command)
72
135
  end
73
- end
74
-
75
- ##
76
- # Retrieve and resolve a locally downloaded Sprout
77
- def Sprout.load_local(path)
78
- data = nil
79
- File.open(path, 'r') do |f|
80
- data = f.read
136
+
137
+ if(confirmation)
138
+ puts "All Sprout gems have been successfully uninstalled"
139
+ elsif(count > 0)
140
+ puts "Some Sprout gems have been left on the system"
141
+ else
142
+ puts "No Sprout gems were found on this system"
81
143
  end
82
- data = ERB.new(data, nil, '>').result(binding)
83
- begin
84
- sprout = YAML.load(data)
85
- rescue StandardError => e
86
- Log.puts("[ERROR] An invalid sprout definition was encountered at: [#{path}] with:\n\n#{data}\n\nPlease try again...")
87
- if(File.exists?(path))
88
- File.delete(path)
144
+
145
+ # Now clear out the cache
146
+ cache = File.dirname(File.dirname(Sprout.sprout_cache))
147
+
148
+ if(File.exists?(cache))
149
+ puts "\n[WARNING]\n\nAbout to irrevocably destroy the sprout cache at:\n\n#{cache}\n\n"
150
+ puts "Are you absolutely sure? [Yn]"
151
+ response = $stdin.gets.chomp!
152
+ if(response.downcase.index('y'))
153
+ FileUtils.rm_rf(cache)
154
+ else
155
+ puts "Leaving the Sprout file cache in tact...."
89
156
  end
90
- raise UsageError.new('Invalid Sprout definiton')
157
+ else
158
+ puts "No cached files found on this system"
91
159
  end
92
- sprout.resolve
93
- return sprout
94
- end
95
-
96
- def Sprout.update=(update)
97
- @@update = update
160
+
161
+ puts "To completely remove sprouts now, run:"
162
+ puts " #{get_gem_preamble} uninstall sprout"
98
163
  end
99
164
 
100
- def Sprout.base_url
101
- return @@base_url
165
+ # Build up the platform-specific preamble required
166
+ # to call the gem binary from Kernel.execute
167
+ def self.get_gem_preamble
168
+ usr = User.new()
169
+ if(!usr.is_a?(WinUser))
170
+ # Everyone but Win and Cygwin users get 'sudo '
171
+ return "sudo gem"
172
+ elsif(!usr.is_a?(CygwinUser))
173
+ # We're in the DOS Shell
174
+ return "ruby #{get_executable_from_path('gem')}"
175
+ end
176
+ # We're either a CygwinUser or some other non-sudo supporter
177
+ return 'gem'
102
178
  end
103
179
 
104
- def Sprout.update
105
- return @@update
106
- end
107
-
108
- ##
109
- # Begin loading and resolving this Sprout instance
110
- # and recursively call on dependencies
111
- def resolve
112
- begin
113
- load_target
114
- load_dependencies
115
- rescue StandardError => e
116
- puts "[ERROR] Sprout '#{name}' encountered an error, this may prevent your project from working correctly!"
117
- puts e
118
- puts e.backtrace
180
+ # Retrieve the full path to an executable that is
181
+ # available in the system path
182
+ def self.get_executable_from_path(exe)
183
+ path = ENV['PATH']
184
+ file_path = nil
185
+ path.split(get_path_delimiter).each do |p|
186
+ file_path = File.join(p, exe)
187
+ # file_path = file_path.split("/").join("\\")
188
+ # file_path = file_path.split("\\").join("/")
189
+ if(File.exists?(file_path))
190
+ return User.clean_path(file_path)
191
+ end
119
192
  end
193
+ return nil
120
194
  end
121
195
 
122
- def execute
123
- dependencies.each do |dep|
124
- dep.execute
196
+ def self.get_path_delimiter
197
+ usr = User.new
198
+ if(usr.is_a?(WinUser) && !usr.is_a?(CygwinUser))
199
+ return ';'
200
+ else
201
+ return ':'
125
202
  end
126
203
  end
127
204
 
128
- def post_install
129
- if(target.nil?)
130
- return nil
205
+ def self.remove_gems_confirmation
206
+ msg =<<EOF
207
+ About to uninstall all RubyGems that match 'sprout-'....
208
+ Are you sure you want to do this? [Yn]
209
+ EOF
210
+ puts msg
211
+ response = $stdin.gets.chomp!
212
+ if(response.downcase.index('y'))
213
+ return true
131
214
  end
132
- return target.post_install
215
+ return false
133
216
  end
134
217
 
135
- ##
136
- # Load the remote file target associated with this sprout instance
137
- def load_target
138
- target = get_platform_target
139
- if(target)
140
- # Forward type name so that RemoteFileTargets can place
141
- # downloaded files into the appropriate user home folder
142
- target.type = type
143
- target.resolve
218
+ # Retrieve the file target to an executable by sprout name. Usually, these are tool sprouts.
219
+ # * +name+ Full sprout gem name that contains an executable file
220
+ # * +archive_path+ Optional parameter for tools that contain more than one executable, or for
221
+ # when you don't want to use the default executable presented by the tool. For example, the Flex 2 SDK
222
+ # has many executables, when this method is called for them, one might use something like:
223
+ # Sprout::Sprout.get_executable('sprout-flex2sdk-tool', 'bin/mxmlc')
224
+ # * +version+ Optional parameter to specify a particular gem version for this executable
225
+ def self.get_executable(name, archive_path=nil, version=nil)
226
+ target = self.sprout(name, version)
227
+ if(archive_path)
228
+ # If caller sent in a relative path to an executable (e.g., bin/mxmlc), use it
229
+ exe = File.join(target.installed_path, archive_path)
230
+ if(User.new.is_a?(WinUser) && !archive_path.match(/.exe$/))
231
+ # If we're on Win (even Cygwin), add .exe to support custom binaries (see sprout-flex2sdk-tool)
232
+ exe << '.exe'
233
+ end
234
+ elsif(target.url)
235
+ # Otherwise, use the default path to an executable if the RemoteFileTarget has a url prop
236
+ exe = File.join(target.installed_path, target.archive_path)
237
+ else
238
+ # Otherwise attempt to run the feature from the system path
239
+ exe = target.archive_path
144
240
  end
241
+
242
+ if(File.exists?(exe) && File.stat(exe).mode != 33261)
243
+ File.chmod 0755, exe
244
+ end
245
+
246
+ return exe
145
247
  end
146
248
 
147
- ##
148
- # Take the array of string dependency names
149
- # load each dependency YAML file, and replace
150
- # the array with resolved Sprout instances
151
- # Tell each dependency to load it's own
152
- # dependencies
153
- def load_dependencies(loaded_deps=nil)
154
- loaded_deps = (loaded_deps.nil?) ? [name] : loaded_deps # Don't reload deps have already been loaded
155
- deps = []
156
-
157
- if(dependencies)
158
- dependencies.each do |dep|
159
- dep.values.each do |name|
160
- if(!loaded_deps.index(name))
161
- dep = Sprout.load(name)
162
- loaded_deps << name
163
- deps << dep
164
- end
165
- end
166
- end
249
+ # Allows us to easily download and install RubyGem sprouts by name and
250
+ # version.
251
+ # Returns a RubyGem Gem Spec[http://rubygems.org/read/chapter/20]
252
+ # when installation is complete. If the installed gem has a Ruby file
253
+ # configured to 'autorequire', that file will also be required by this
254
+ # method so that any provided Ruby functionality will be immediately
255
+ # available to client scripts. If the installed gem contains a
256
+ # 'sprout.spec' file, any RemoteFileTargets will be resolved synchronously
257
+ # and those files will be available in the Sprout::Sprout.cache.
258
+ #
259
+ def self.sprout(name, version=nil)
260
+ name = sprout_to_gem_name(name)
261
+ gem_spec = self.find_gem_spec(name, version)
262
+ sprout_spec_path = File.join(gem_spec.full_gem_path, @@spec)
263
+
264
+ if(gem_spec.autorequire)
265
+ $:.push(File.join(gem_spec.full_gem_path, 'lib'))
266
+ require gem_spec.autorequire
267
+ end
268
+ if(File.exists?(sprout_spec_path))
269
+ # Ensure the requisite files get downloaded and unpacked
270
+ Builder.build(sprout_spec_path, gem_file_cache(gem_spec.name, gem_spec.version))
271
+ else
272
+ return gem_spec
167
273
  end
168
- @dependencies = deps
169
- end
170
-
171
- ##
172
- # Insert search locations (Array) 'base paths' for Sprout.load operations
173
- def Sprout.insert_locations(locations)
174
- @@base_urls = Sprout.clean_locations(locations) + @@base_urls
175
- end
176
-
177
- # TODO: Be smart about added a trailing '/'
178
- # Try to ensure that only valid URLs get
179
- # added to the list of locations - throw
180
- # something informative if needed.
181
- def Sprout.clean_locations(locations)
182
- return locations
183
274
  end
184
275
 
185
- ##
186
- # The system-specific home folder for Sprout application data
187
- # e.g., On OS X, /Users/you/Library/Sprouts
188
- # e.g., On Win, C:\Documents And Settings\you\Local Settings\Application Data\Sprouts
189
- def Sprout.home
190
- if(@@home.nil?)
191
- @@home = User.new().application_home(:sprouts)
276
+ # Return sprout-#{name}-bundle for any name that does not begin with 'sprout-'. This was used early on in development
277
+ # but should possibly be removed as we move forward and try to support arbitrary RubyGems.
278
+ def self.sprout_to_gem_name(name)
279
+ if(!name.match(/^sprout-/))
280
+ name = "sprout-#{name}-bundle"
192
281
  end
282
+ return name
283
+ end
284
+
285
+ # Return the home directory for this Sprout installation
286
+ def self.home
193
287
  return @@home
194
288
  end
195
289
 
196
- ##
197
- # The nearest valid project path or current working directory
198
- # if no rakefile was found in parent paths
199
- def Sprout.project_path(path=nil)
200
- if(@@project_path.nil?)
201
- path = (path.nil?) ? Dir.pwd : path;
202
- path = Sprout.get_project_path(path)
203
- if(path.nil?)
204
- path = Dir.pwd
205
- end
206
- @@project_path = path
207
- end
208
- return @@project_path
290
+ # Return the location on disk where this installation of Sprouts stores it's cached files.
291
+ # If the currently installed version of Sprouts were 0.7 and your system username were 'foo'
292
+ # this would return the following locations:
293
+ # * +OSX+ /Users/foo/Library/Sprouts/cache/0.7
294
+ # * +Windows+ C:/Documents And Settings/foo/Local Settings/Application Data/Sprouts/cache/0.7
295
+ # * +Linux+ ~/.sprouts/cache/0.7
296
+ def self.sprout_cache
297
+ home = User.application_home(@@name)
298
+ return File.join(home, @@cache, "#{VERSION::MAJOR}.#{VERSION::MINOR}")
209
299
  end
210
300
 
211
- def Sprout.project_path=(path)
212
- @@project_path = path
301
+ # Return the +sprout_cache+ combined with the passed in +name+ and +version+ so that you will get
302
+ # a cache location for a specific gem.
303
+ def self.gem_file_cache(name, version)
304
+ return File.join(sprout_cache, "#{name}-#{version}")
213
305
  end
214
306
 
215
- def Sprout.get_project_path(path)
216
- if(path.nil? || path == '/' || path.match(/[A-Z]\:\//))
217
- return nil
307
+ # Retrieve the RubyGems gem spec for a particular gem +name+ that meets the provided +requirements+.
308
+ # +requirements+ are provided as a string value like:
309
+ # '>= 0.0.1'
310
+ # or
311
+ # '0.0.1'
312
+ # This method will actually download and install the provided gem by +name+ and +requirements+ if
313
+ # it is not found locally on the system.
314
+ def self.find_gem_spec(name, requirements=nil, recursed=false)
315
+ specs = Gem::cache.search(/.*#{name}$/)
316
+ requirement = nil
317
+ if(requirements)
318
+ requirement = Gem::Requirement.new(requirements)
218
319
  end
219
- @@default_rakefiles.each do |file|
220
- if(File.exists?(File.join(path, file)))
221
- return path
320
+ specs.each do |spec|
321
+ if(requirements)
322
+ if(requirement.satisfied_by?(spec.version))
323
+ return spec
324
+ end
325
+ else
326
+ return spec
222
327
  end
223
328
  end
224
- return Sprout.get_project_path(File.dirname(path))
225
- end
226
-
227
- ##
228
- # Offline storage location for network entities like
229
- # Sprout definitions, tasks and archives
230
- def Sprout.cache
231
- if(@@cache.nil?)
232
- @@cache = File.join(Sprout.home, 'cache')
233
- end
234
- return @@cache
235
- end
236
-
237
- def Sprout.config_cache
238
- if(@@config_cache.nil?)
239
- @@config_cache = File.join(Sprout.cache, 'sprouts')
329
+
330
+ if(recursed)
331
+ raise SproutError.new("Gem Spec not found for #{name} #{requirements}")
332
+ else
333
+ msg = ">> Loading gem [#{name}]"
334
+ msg << " #{requirements}" if requirements
335
+ msg << " from #{gem_sources.join(', ')} with it's dependencies"
336
+ Log.puts msg
337
+ parts = []
338
+ parts << "ins"
339
+ parts << "-r"
340
+ parts << name
341
+ # This url should be removed once released, released gems should be hosted from the rubyforge
342
+ # project, and development gems will be hosted on our domain.
343
+ parts << "--source #{gem_sources.join(' --source ')}" if(Log.debug || name.index('sprout-'))
344
+ parts << "-v #{requirements}" unless requirements.nil?
345
+
346
+ self.load_gem(parts.join(" "))
347
+ Gem::cache.refresh!
348
+ return find_gem_spec(name, requirements, true)
240
349
  end
241
- return @@config_cache
242
350
  end
243
351
 
244
- ##
245
- # List of potential rakefile names for project_path searching
246
- def Sprout.default_rakefiles
247
- return @@default_rakefiles
352
+ def self.load_gem(args)
353
+ # This must use a 'system' call because RubyGems
354
+ # sends an 'exit'?
355
+ system("#{get_gem_preamble} #{args}")
248
356
  end
249
357
 
250
- def Sprout.rakefile
251
- @@default_rakefiles.each do |name|
252
- file = File.join(Sprout.project_path, name)
253
- if(File.exists?(file))
254
- return file
255
- end
256
- end
257
- return nil
258
- end
259
-
260
- ##
261
- # Reset static values for test purposes
262
- def Sprout.init_values
263
- User.init_values
264
- @@project_path = nil
265
- @@config_cache = nil
266
- @@cache = nil
267
- @@home = nil
268
- end
269
-
270
358
  ##
271
359
  # List of files to ignore when copying project templates
272
360
  # These files will not be copied
273
361
  @@COPY_IGNORE_FILES = ['.', '..', '.svn', '.DS_Store', 'CVS', '.cvs' 'Thumbs.db', '__MACOSX', '.Trashes', 'Desktop DB', 'Desktop DF']
274
362
  # Do not copy files found in the ignore_files list
275
- def Sprout.ignore_file? file
363
+ def self.ignore_file? file
276
364
  @@COPY_IGNORE_FILES.each do |name|
277
365
  if(name == file)
278
366
  return true
@@ -281,84 +369,88 @@ module PatternPark
281
369
  return false
282
370
  end
283
371
 
284
- ##
285
- # The project name as entered in the sprout shell command
286
- def Sprout.project_name=(name)
287
- @@project_name = name
288
- end
289
-
290
- def Sprout.project_name
291
- return @@project_name
292
- end
293
-
294
- def get_platform_target
295
- usr = User.new
296
- @target = nil
297
- if(targets)
298
- universal_target = nil
299
- platform = usr.platform.to_s
300
- # puts "platform: #{platform}"
301
- targets.each do |t|
302
- if(t.platform == platform)
303
- @target = t
304
- elsif(t.platform == @@universal)
305
- universal_target = t
306
- end
307
- end
308
- if(target.nil? && universal_target)
309
- @target = universal_target
310
- end
372
+ def self.gem_sources=(sources) # :nodoc:
373
+ if(sources.is_a?(String))
374
+ # TODO: Clean up the string that is sent in,
375
+ # maybe even split space or comma-delimited?
376
+ sources = [sources]
311
377
  end
312
- return @target
378
+ @@gem_sources = sources
313
379
  end
314
380
 
315
- ##
316
- # The first FileTarget that is applicable for this
317
- # client operating system
318
- def target
319
- return @target
381
+ # TODO: Should be updated after release so that all gems are
382
+ # loaded form rubyforge instead of projectsprouts, only development
383
+ # gems will continue to be hosted at this default domain.
384
+ def self.gem_sources # :nodoc:
385
+ @@gem_sources ||= ['http://gems.rubyforge.org']
320
386
  end
321
387
 
322
- def executable
323
- return target.executable
388
+ def self.project_name=(name) # :nodoc:
389
+ @@project_name = name
324
390
  end
325
391
 
326
- def archive_path
327
- return File.join(install_path, target.archive_path)
392
+ # Return the current project_name assuming someone has already set it, otherwise return an empty string
393
+ def self.project_name
394
+ @@project_name ||= ''
328
395
  end
329
396
 
330
- def install_path
331
- target.install_path
397
+ def self.project_path=(path) # :nodoc:
398
+ @@project_rakefile = child_rakefile(path)
399
+ @@project_path = path
332
400
  end
333
401
 
334
- def downloaded_path
335
- target.downloaded_path
402
+ # project_path should step backward in the file system
403
+ # until it encounters a rakefile. The parent directory
404
+ # of that rakefile should be returned.
405
+ # If no rakefile is found, it should return Dir.pwd
406
+ def self.project_path
407
+ @@project_path ||= get_implicit_project_path(Dir.pwd)
336
408
  end
337
409
 
338
- def config_path(name)
339
- return Sprout.config_cache + name
410
+ # Return the rakefile in the current +project_path+
411
+ def self.project_rakefile
412
+ return @@project_rakefile ||= nil
413
+ end
414
+
415
+ private
416
+
417
+ # Look in the provided +dir+ for files that meet the criteria to be a valid Rakefile.
418
+ def self.child_rakefile(dir)
419
+ @@default_rakefiles.each do |file|
420
+ rake_path = File.join(dir, file)
421
+ if(File.exists?(rake_path))
422
+ return rake_path
423
+ end
424
+ end
425
+ return nil
340
426
  end
427
+
428
+ def self.get_implicit_project_path(path)
429
+ # We have recursed to the root of the filesystem, return nil
430
+ if(path.nil? || path == '/' || path.match(/[A-Z]\:\//))
431
+ return Dir.pwd
432
+ end
433
+ # Look for a rakefile as a child of the current path
434
+ if(child_rakefile(path))
435
+ return path
436
+ end
437
+ # No rakefile and no root found, check in parent dir
438
+ return Sprout.get_implicit_project_path(File.dirname(path))
439
+ end
440
+
341
441
  end
442
+ end
342
443
 
343
- require 'singleton'
344
- require 'progress_bar'
345
- require 'process_runner'
346
- require 'template_resolver'
347
- require 'platform'
348
- require 'user'
349
- require 'project'
350
- require 'library'
351
- require 'template'
352
- require 'task'
353
- require 'command'
354
- require 'tool'
355
- require 'remote_file_loader'
356
- require 'file_target'
357
- require 'remote_file_target'
358
-
359
- require 'project_model'
360
- require 'generate'
444
+ # Set an array of URLs to use as gem repositories when loading Sprout gems.
445
+ # Any rakefile that requires the sprout gem can use this method as follows:
446
+ #
447
+ # set_sources ['http://gems.yourdomain.com']
448
+ #
449
+ def set_sources(sources)
450
+ Sprout::Sprout.gem_sources = sources
361
451
  end
362
452
 
363
- cache = File.join(PatternPark::Sprout.cache)
364
- $:.push(cache)
453
+ # Helper method that will download and install remote sprouts by name and version
454
+ def sprout(name, version=nil)
455
+ Sprout::Sprout.sprout(name, version)
456
+ end