pluginfactory 1.0.2 → 1.0.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,62 @@
1
+ #
2
+ # Dependency-checking and Installation Rake Tasks
3
+ # $Id: dependencies.rb 10 2008-07-18 15:52:48Z deveiant $
4
+ #
5
+
6
+ require 'rubygems/dependency_installer'
7
+ require 'rubygems/source_index'
8
+ require 'rubygems/requirement'
9
+ require 'rubygems/doc_manager'
10
+
11
+ ### Install the specified +gems+ if they aren't already installed.
12
+ def install_gems( *gems )
13
+ gems.flatten!
14
+
15
+ defaults = Gem::DependencyInstaller::DEFAULT_OPTIONS.merge({
16
+ :generate_rdoc => true,
17
+ :generate_ri => true,
18
+ :install_dir => Gem.dir,
19
+ :format_executable => false,
20
+ :test => false,
21
+ :version => Gem::Requirement.default,
22
+ })
23
+
24
+ # Check for root
25
+ if Process.euid != 0
26
+ $stderr.puts "This probably won't work, as you aren't root, but I'll try anyway"
27
+ end
28
+
29
+ gemindex = Gem::SourceIndex.from_installed_gems
30
+
31
+ gems.each do |gemname|
32
+ if (( specs = gemindex.search(gemname) )) && ! specs.empty?
33
+ log "Version %s of %s is already installed; skipping..." %
34
+ [ specs.first.version, specs.first.name ]
35
+ next
36
+ end
37
+
38
+ rgv = Gem::Version.new( Gem::RubyGemsVersion )
39
+ installer = nil
40
+
41
+ log "Trying to install #{gemname.inspect}..."
42
+ if rgv >= Gem::Version.new( '1.1.1' )
43
+ installer = Gem::DependencyInstaller.new
44
+ installer.install( gemname )
45
+ else
46
+ installer = Gem::DependencyInstaller.new( gemname )
47
+ installer.install
48
+ end
49
+
50
+ installer.installed_gems.each do |spec|
51
+ log "Installed: %s" % [ spec.full_name ]
52
+ end
53
+
54
+ end
55
+ end
56
+
57
+
58
+ ### Task: install gems for development tasks
59
+ task :install_dependencies do
60
+ install_gems( DEPENDENCIES.keys )
61
+ end
62
+
data/rake/helpers.rb ADDED
@@ -0,0 +1,382 @@
1
+ #####################################################################
2
+ ### G L O B A L H E L P E R F U N C T I O N S
3
+ #####################################################################
4
+
5
+ require 'pathname'
6
+ require 'readline'
7
+
8
+ # Set some ANSI escape code constants (Shamelessly stolen from Perl's
9
+ # Term::ANSIColor by Russ Allbery <rra@stanford.edu> and Zenin <zenin@best.com>
10
+ ANSI_ATTRIBUTES = {
11
+ 'clear' => 0,
12
+ 'reset' => 0,
13
+ 'bold' => 1,
14
+ 'dark' => 2,
15
+ 'underline' => 4,
16
+ 'underscore' => 4,
17
+ 'blink' => 5,
18
+ 'reverse' => 7,
19
+ 'concealed' => 8,
20
+
21
+ 'black' => 30, 'on_black' => 40,
22
+ 'red' => 31, 'on_red' => 41,
23
+ 'green' => 32, 'on_green' => 42,
24
+ 'yellow' => 33, 'on_yellow' => 43,
25
+ 'blue' => 34, 'on_blue' => 44,
26
+ 'magenta' => 35, 'on_magenta' => 45,
27
+ 'cyan' => 36, 'on_cyan' => 46,
28
+ 'white' => 37, 'on_white' => 47
29
+ }
30
+
31
+
32
+ MULTILINE_PROMPT = <<-'EOF'
33
+ Enter one or more values for '%s'.
34
+ A blank line finishes input.
35
+ EOF
36
+
37
+
38
+ CLEAR_TO_EOL = "\e[K"
39
+ CLEAR_CURRENT_LINE = "\e[2K"
40
+
41
+
42
+ ### Output a logging message
43
+ def log( *msg )
44
+ output = colorize( msg.flatten.join(' '), 'cyan' )
45
+ $deferr.puts( output )
46
+ end
47
+
48
+
49
+ ### Output a logging message if tracing is on
50
+ def trace( *msg )
51
+ return unless $trace
52
+ output = colorize( msg.flatten.join(' '), 'yellow' )
53
+ $deferr.puts( output )
54
+ end
55
+
56
+
57
+ ### Run the specified command +cmd+ with system(), failing if the execution
58
+ ### fails.
59
+ def run( *cmd )
60
+ cmd.flatten!
61
+
62
+ log( cmd.collect {|part| part =~ /\s/ ? part.inspect : part} )
63
+ if $dryrun
64
+ $deferr.puts "(dry run mode)"
65
+ else
66
+ system( *cmd )
67
+ unless $?.success?
68
+ fail "Command failed: [%s]" % [cmd.join(' ')]
69
+ end
70
+ end
71
+ end
72
+
73
+
74
+ ### Open a pipe to a process running the given +cmd+ and call the given block with it.
75
+ def pipeto( *cmd )
76
+ $DEBUG = true
77
+
78
+ cmd.flatten!
79
+ log( "Opening a pipe to: ", cmd.collect {|part| part =~ /\s/ ? part.inspect : part} )
80
+ if $dryrun
81
+ $deferr.puts "(dry run mode)"
82
+ else
83
+ open( '|-', 'w+' ) do |io|
84
+
85
+ # Parent
86
+ if io
87
+ yield( io )
88
+
89
+ # Child
90
+ else
91
+ exec( *cmd )
92
+ fail "Command failed: [%s]" % [cmd.join(' ')]
93
+ end
94
+ end
95
+ end
96
+ end
97
+
98
+
99
+ ### Download the file at +sourceuri+ via HTTP and write it to +targetfile+.
100
+ def download( sourceuri, targetfile=nil )
101
+ oldsync = $defout.sync
102
+ $defout.sync = true
103
+ require 'net/http'
104
+ require 'uri'
105
+
106
+ targetpath = Pathname.new( targetfile )
107
+
108
+ log "Downloading %s to %s" % [sourceuri, targetfile]
109
+ targetpath.open( File::WRONLY|File::TRUNC|File::CREAT, 0644 ) do |ofh|
110
+
111
+ url = sourceuri.is_a?( URI ) ? sourceuri : URI.parse( sourceuri )
112
+ downloaded = false
113
+ limit = 5
114
+
115
+ until downloaded or limit.zero?
116
+ Net::HTTP.start( url.host, url.port ) do |http|
117
+ req = Net::HTTP::Get.new( url.path )
118
+
119
+ http.request( req ) do |res|
120
+ if res.is_a?( Net::HTTPSuccess )
121
+ log "Downloading..."
122
+ res.read_body do |buf|
123
+ ofh.print( buf )
124
+ end
125
+ downloaded = true
126
+ puts "done."
127
+
128
+ elsif res.is_a?( Net::HTTPRedirection )
129
+ url = URI.parse( res['location'] )
130
+ log "...following redirection to: %s" % [ url ]
131
+ limit -= 1
132
+ sleep 0.2
133
+ next
134
+
135
+ else
136
+ res.error!
137
+ end
138
+ end
139
+ end
140
+ end
141
+
142
+ end
143
+
144
+ return targetpath
145
+ ensure
146
+ $defout.sync = oldsync
147
+ end
148
+
149
+
150
+ ### Return the fully-qualified path to the specified +program+ in the PATH.
151
+ def which( program )
152
+ ENV['PATH'].split(/:/).
153
+ collect {|dir| Pathname.new(dir) + program }.
154
+ find {|path| path.exist? && path.executable? }
155
+ end
156
+
157
+
158
+ ### Create a string that contains the ANSI codes specified and return it
159
+ def ansi_code( *attributes )
160
+ attributes.flatten!
161
+ attributes.collect! {|at| at.to_s }
162
+ # $deferr.puts "Returning ansicode for TERM = %p: %p" %
163
+ # [ ENV['TERM'], attributes ]
164
+ return '' unless /(?:vt10[03]|xterm(?:-color)?|linux|screen)/i =~ ENV['TERM']
165
+ attributes = ANSI_ATTRIBUTES.values_at( *attributes ).compact.join(';')
166
+
167
+ # $deferr.puts " attr is: %p" % [attributes]
168
+ if attributes.empty?
169
+ return ''
170
+ else
171
+ return "\e[%sm" % attributes
172
+ end
173
+ end
174
+
175
+
176
+ ### Colorize the given +string+ with the specified +attributes+ and return it, handling
177
+ ### line-endings, color reset, etc.
178
+ def colorize( *args )
179
+ string = ''
180
+
181
+ if block_given?
182
+ string = yield
183
+ else
184
+ string = args.shift
185
+ end
186
+
187
+ ending = string[/(\s)$/] || ''
188
+ string = string.rstrip
189
+
190
+ return ansi_code( args.flatten ) + string + ansi_code( 'reset' ) + ending
191
+ end
192
+
193
+
194
+ ### Output the specified <tt>msg</tt> as an ANSI-colored error message
195
+ ### (white on red).
196
+ def error_message( msg, details='' )
197
+ $deferr.puts colorize( 'bold', 'white', 'on_red' ) { msg } + details
198
+ end
199
+ alias :error :error_message
200
+
201
+
202
+ ### Highlight and embed a prompt control character in the given +string+ and return it.
203
+ def make_prompt_string( string )
204
+ return CLEAR_CURRENT_LINE + colorize( 'bold', 'green' ) { string + ' ' }
205
+ end
206
+
207
+
208
+ ### Output the specified <tt>prompt_string</tt> as a prompt (in green) and
209
+ ### return the user's input with leading and trailing spaces removed. If a
210
+ ### test is provided, the prompt will repeat until the test returns true.
211
+ ### An optional failure message can also be passed in.
212
+ def prompt( prompt_string, failure_msg="Try again." ) # :yields: response
213
+ prompt_string.chomp!
214
+ prompt_string << ":" unless /\W$/.match( prompt_string )
215
+ response = nil
216
+
217
+ begin
218
+ prompt = make_prompt_string( prompt_string )
219
+ response = Readline.readline( prompt ) || ''
220
+ response.strip!
221
+ if block_given? && ! yield( response )
222
+ error_message( failure_msg + "\n\n" )
223
+ response = nil
224
+ end
225
+ end while response.nil?
226
+
227
+ return response
228
+ end
229
+
230
+
231
+ ### Prompt the user with the given <tt>prompt_string</tt> via #prompt,
232
+ ### substituting the given <tt>default</tt> if the user doesn't input
233
+ ### anything. If a test is provided, the prompt will repeat until the test
234
+ ### returns true. An optional failure message can also be passed in.
235
+ def prompt_with_default( prompt_string, default, failure_msg="Try again." )
236
+ response = nil
237
+
238
+ begin
239
+ default ||= '~'
240
+ response = prompt( "%s [%s]" % [ prompt_string, default ] )
241
+ response = default.to_s if !response.nil? && response.empty?
242
+
243
+ trace "Validating reponse %p" % [ response ]
244
+
245
+ # the block is a validator. We need to make sure that the user didn't
246
+ # enter '~', because if they did, it's nil and we should move on. If
247
+ # they didn't, then call the block.
248
+ if block_given? && response != '~' && ! yield( response )
249
+ error_message( failure_msg + "\n\n" )
250
+ response = nil
251
+ end
252
+ end while response.nil?
253
+
254
+ return nil if response == '~'
255
+ return response
256
+ end
257
+
258
+
259
+ ### Prompt for an array of values
260
+ def prompt_for_multiple_values( label, default=nil )
261
+ $stderr.puts( MULTILINE_PROMPT % [label] )
262
+ if default
263
+ $stderr.puts "Enter a single blank line to keep the default:\n %p" % [ default ]
264
+ end
265
+
266
+ results = []
267
+ result = nil
268
+
269
+ begin
270
+ result = Readline.readline( make_prompt_string("> ") )
271
+ if result.nil? || result.empty?
272
+ results << default if default && results.empty?
273
+ else
274
+ results << result
275
+ end
276
+ end until result.nil? || result.empty?
277
+
278
+ return results.flatten
279
+ end
280
+
281
+
282
+ ### Turn echo and masking of input on/off. Based on similar code in
283
+ ### Ruby-Password by Ian Macdonald <ian@caliban.org>.
284
+ def noecho( masked=false )
285
+ require 'termios'
286
+
287
+ rval = nil
288
+ term = Termios.getattr( $stdin )
289
+
290
+ begin
291
+ term.c_lflag &= ~Termios::ECHO
292
+ term.c_lflag &= ~Termios::ICANON if masked
293
+
294
+ rval = yield
295
+ ensure
296
+ term.c_lflag |= ( Termios::ECHO | Termios::ICANON )
297
+ Termios.setattr( $stdin, Termios::TCSANOW, term )
298
+ end
299
+
300
+ return rval
301
+ end
302
+
303
+
304
+ ### Prompt the user for her password, turning off echo if the 'termios' module is
305
+ ### available.
306
+ def prompt_for_password( prompt="Password: " )
307
+ return noecho( true ) do
308
+ $stderr.print( prompt )
309
+ ($stdin.gets || '').chomp
310
+ end
311
+ end
312
+
313
+
314
+ ### Display a description of a potentially-dangerous task, and prompt
315
+ ### for confirmation. If the user answers with anything that begins
316
+ ### with 'y', yield to the block, else raise with an error.
317
+ def ask_for_confirmation( description )
318
+ puts description
319
+
320
+ answer = prompt_with_default( "Continue?", 'n' ) do |input|
321
+ input =~ /^[yn]/i
322
+ end
323
+
324
+ case answer
325
+ when /^y/i
326
+ yield
327
+ else
328
+ error "Aborted."
329
+ fail
330
+ end
331
+ end
332
+
333
+
334
+ ### Search line-by-line in the specified +file+ for the given +regexp+, returning the
335
+ ### first match, or nil if no match was found. If the +regexp+ has any capture groups,
336
+ ### those will be returned in an Array, else the whole matching line is returned.
337
+ def find_pattern_in_file( regexp, file )
338
+ rval = nil
339
+
340
+ File.open( file, 'r' ).each do |line|
341
+ if (( match = regexp.match(line) ))
342
+ rval = match.captures.empty? ? match[0] : match.captures
343
+ break
344
+ end
345
+ end
346
+
347
+ return rval
348
+ end
349
+
350
+
351
+ ### Get a list of the file or files to run rspec on.
352
+ def rspec_files
353
+ if ENV['class']
354
+ classname = ENV['class']
355
+ spec_file = SPECSDIR + "#{classname}_spec.rb"
356
+ raise "Can't find the spec file for the class '#{classname}'" unless spec_file.exist?
357
+ return [ spec_file ]
358
+ else
359
+ return SPEC_FILES
360
+ end
361
+ end
362
+
363
+
364
+ ### Invoke the user's editor on the given +filename+ and return the exit code
365
+ ### from doing so.
366
+ def edit( filename )
367
+ editor = ENV['EDITOR'] || ENV['VISUAL'] || DEFAULT_EDITOR
368
+ system editor, filename
369
+ unless $?.success?
370
+ fail "Editor exited uncleanly."
371
+ end
372
+ end
373
+
374
+
375
+ ### Extract all the non Rake-target arguments from ARGV and return them.
376
+ def get_target_args
377
+ args = ARGV.reject {|arg| Rake::Task.task_defined?(arg) }
378
+ return args
379
+ end
380
+
381
+
382
+