pg 0.9.0-x86-mswin32 → 0.11.0pre229-x86-mswin32

Sign up to get free protection for your applications and to get access to all the features.
data/ext/pg.h CHANGED
@@ -1,3 +1,6 @@
1
+ #ifndef PG_H_C98VS4AD
2
+ #define PG_H_C98VS4AD
3
+
1
4
  #include <stdio.h>
2
5
  #include <stdlib.h>
3
6
  #include <sys/types.h>
@@ -47,3 +50,4 @@ __declspec(dllexport)
47
50
  #endif
48
51
  void Init_pg_ext(void);
49
52
 
53
+ #endif /* end of include guard: PG_H_C98VS4AD */
Binary file
Binary file
data/lib/pg.rb CHANGED
@@ -1,11 +1,16 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
- # Load the correct version if it's a Windows binary gem
4
- if RUBY_PLATFORM =~/(mswin|mingw)/i
5
- major_minor = RUBY_VERSION[ /^(\d+\.\d+)/ ] or
6
- raise "Oops, can't extract the major/minor version from #{RUBY_VERSION.dump}"
7
- require "#{major_minor}/pg_ext"
8
- else
3
+ begin
9
4
  require 'pg_ext'
5
+ rescue LoadError => err
6
+ # If it's a Windows binary gem, try the <major>.<minor> subdirectory
7
+ if RUBY_PLATFORM =~/(mswin|mingw)/i
8
+ major_minor = RUBY_VERSION[ /^(\d+\.\d+)/ ] or
9
+ raise "Oops, can't extract the major/minor version from #{RUBY_VERSION.dump}"
10
+ require "#{major_minor}/pg_ext"
11
+ else
12
+ raise
13
+ end
14
+
10
15
  end
11
16
 
@@ -0,0 +1,123 @@
1
+ #
2
+ # Documentation Rake tasks
3
+ #
4
+
5
+ require 'rake/clean'
6
+
7
+
8
+ # Append docs/lib to the load path if it exists for documentation
9
+ # helpers.
10
+ DOCSLIB = DOCSDIR + 'lib'
11
+ $LOAD_PATH.unshift( DOCSLIB.to_s ) if DOCSLIB.exist?
12
+
13
+ # Make relative string paths of all the stuff we need to generate docs for
14
+ DOCFILES = Rake::FileList[ LIB_FILES + EXT_FILES + GEMSPEC.extra_rdoc_files ]
15
+
16
+ # Documentation coverage constants
17
+ COVERAGE_DIR = BASEDIR + 'coverage'
18
+ COVERAGE_REPORT = COVERAGE_DIR + 'documentation.txt'
19
+
20
+
21
+ # Prefer YARD, fallback to RDoc
22
+ begin
23
+ require 'yard'
24
+ require 'yard/rake/yardoc_task'
25
+
26
+ # Undo the lazy-assed monkeypatch yard/globals.rb installs and
27
+ # re-install them as mixins as they should have been from the
28
+ # start
29
+ # <metamonkeypatch>
30
+ class Object
31
+ remove_method :log
32
+ remove_method :P
33
+ end
34
+
35
+ module YardGlobals
36
+ def P(namespace, name = nil)
37
+ namespace, name = nil, namespace if name.nil?
38
+ YARD::Registry.resolve(namespace, name, false, true)
39
+ end
40
+
41
+ def log
42
+ YARD::Logger.instance
43
+ end
44
+ end
45
+
46
+ class YARD::CLI::Base; include YardGlobals; end
47
+ class YARD::CLI::Command; include YardGlobals; end
48
+ class YARD::Parser::SourceParser; extend YardGlobals; include YardGlobals; end
49
+ class YARD::Parser::CParser; include YardGlobals; end
50
+ class YARD::CodeObjects::Base; include YardGlobals; end
51
+ class YARD::Handlers::Base; include YardGlobals; end
52
+ class YARD::Handlers::Processor; include YardGlobals; end
53
+ class YARD::Serializers::Base; include YardGlobals; end
54
+ class YARD::RegistryStore; include YardGlobals; end
55
+ class YARD::Docstring; include YardGlobals; end
56
+ module YARD::Templates::Helpers::ModuleHelper; include YardGlobals; end
57
+ module YARD::Templates::Helpers::HtmlHelper; include YardGlobals; end
58
+
59
+ if vvec(RUBY_VERSION) >= vvec("1.9.1")
60
+ # Monkeypatched to allow more than two '#' characters at the beginning
61
+ # of the comment line.
62
+ # Patched from yard-0.5.8
63
+ require 'yard/parser/ruby/ruby_parser'
64
+ class YARD::Parser::Ruby::RipperParser < Ripper
65
+ def on_comment(comment)
66
+ visit_ns_token(:comment, comment)
67
+ case comment
68
+ when /\A# @group\s+(.+)\s*\Z/
69
+ @groups.unshift [lineno, $1]
70
+ return
71
+ when /\A# @endgroup\s*\Z/
72
+ @groups.unshift [lineno, nil]
73
+ return
74
+ end
75
+
76
+ comment = comment.gsub(/^\#+\s{0,1}/, '').chomp
77
+ append_comment = @comments[lineno - 1]
78
+
79
+ if append_comment && @comments_last_column == column
80
+ @comments.delete(lineno - 1)
81
+ comment = append_comment + "\n" + comment
82
+ end
83
+
84
+ @comments[lineno] = comment
85
+ @comments_last_column = column
86
+ end
87
+ end # class YARD::Parser::Ruby::RipperParser
88
+ end
89
+
90
+ # </metamonkeypatch>
91
+
92
+ YARD_OPTIONS = [] unless defined?( YARD_OPTIONS )
93
+
94
+ yardoctask = YARD::Rake::YardocTask.new( :apidocs ) do |task|
95
+ task.files = DOCFILES
96
+ task.options = YARD_OPTIONS
97
+ task.options << '--debug' << '--verbose' if $trace
98
+ end
99
+ yardoctask.before = lambda {
100
+ trace "Calling yardoc like:",
101
+ " yardoc %s" % [ quotelist(yardoctask.options + yardoctask.files).join(' ') ]
102
+ }
103
+
104
+ YARDOC_CACHE = BASEDIR + '.yardoc'
105
+ CLOBBER.include( YARDOC_CACHE.to_s )
106
+
107
+ rescue LoadError
108
+ require 'rdoc/task'
109
+
110
+ desc "Build API documentation in #{API_DOCSDIR}"
111
+ RDoc::Task.new( :apidocs ) do |task|
112
+ task.main = "README"
113
+ task.rdoc_files.include( DOCFILES )
114
+ task.rdoc_dir = API_DOCSDIR.to_s
115
+ task.options = RDOC_OPTIONS
116
+ end
117
+ end
118
+
119
+ # Need the DOCFILES to exist to build the API docs
120
+ task :apidocs => DOCFILES
121
+
122
+ CLEAN.include( API_DOCSDIR.to_s )
123
+
@@ -1,4 +1,5 @@
1
1
  # encoding: utf-8
2
+
2
3
  #####################################################################
3
4
  ### G L O B A L H E L P E R F U N C T I O N S
4
5
  #####################################################################
@@ -6,7 +7,6 @@
6
7
 
7
8
  require 'pathname'
8
9
  require 'uri'
9
- require 'open3'
10
10
 
11
11
  begin
12
12
  require 'readline'
@@ -19,417 +19,484 @@ rescue LoadError
19
19
  end
20
20
  end
21
21
 
22
- # Set some ANSI escape code constants (Shamelessly stolen from Perl's
23
- # Term::ANSIColor by Russ Allbery <rra@stanford.edu> and Zenin <zenin@best.com>
24
- ANSI_ATTRIBUTES = {
25
- 'clear' => 0,
26
- 'reset' => 0,
27
- 'bold' => 1,
28
- 'dark' => 2,
29
- 'underline' => 4,
30
- 'underscore' => 4,
31
- 'blink' => 5,
32
- 'reverse' => 7,
33
- 'concealed' => 8,
34
-
35
- 'black' => 30, 'on_black' => 40,
36
- 'red' => 31, 'on_red' => 41,
37
- 'green' => 32, 'on_green' => 42,
38
- 'yellow' => 33, 'on_yellow' => 43,
39
- 'blue' => 34, 'on_blue' => 44,
40
- 'magenta' => 35, 'on_magenta' => 45,
41
- 'cyan' => 36, 'on_cyan' => 46,
42
- 'white' => 37, 'on_white' => 47
43
- }
44
-
45
-
46
- MULTILINE_PROMPT = <<-'EOF'
47
- Enter one or more values for '%s'.
48
- A blank line finishes input.
49
- EOF
50
-
51
-
52
- CLEAR_TO_EOL = "\e[K"
53
- CLEAR_CURRENT_LINE = "\e[2K"
54
-
55
-
56
- ### Output a logging message
57
- def log( *msg )
58
- output = colorize( msg.flatten.join(' '), 'cyan' )
59
- $stderr.puts( output )
60
- end
22
+ module RakefileHelpers
23
+ # Set some ANSI escape code constants (Shamelessly stolen from Perl's
24
+ # Term::ANSIColor by Russ Allbery <rra@stanford.edu> and Zenin <zenin@best.com>
25
+ ANSI_ATTRIBUTES = {
26
+ 'clear' => 0,
27
+ 'reset' => 0,
28
+ 'bold' => 1,
29
+ 'dark' => 2,
30
+ 'underline' => 4,
31
+ 'underscore' => 4,
32
+ 'blink' => 5,
33
+ 'reverse' => 7,
34
+ 'concealed' => 8,
61
35
 
36
+ 'black' => 30, 'on_black' => 40,
37
+ 'red' => 31, 'on_red' => 41,
38
+ 'green' => 32, 'on_green' => 42,
39
+ 'yellow' => 33, 'on_yellow' => 43,
40
+ 'blue' => 34, 'on_blue' => 44,
41
+ 'magenta' => 35, 'on_magenta' => 45,
42
+ 'cyan' => 36, 'on_cyan' => 46,
43
+ 'white' => 37, 'on_white' => 47
44
+ }
62
45
 
63
- ### Output a logging message if tracing is on
64
- def trace( *msg )
65
- return unless $trace
66
- output = colorize( msg.flatten.join(' '), 'yellow' )
67
- $stderr.puts( output )
68
- end
69
46
 
47
+ MULTILINE_PROMPT = <<-'EOF'
48
+ Enter one or more values for '%s'.
49
+ A blank line finishes input.
50
+ EOF
70
51
 
71
- ### Return the specified args as a string, quoting any that have a space.
72
- def quotelist( *args )
73
- return args.flatten.collect {|part| part =~ /\s/ ? part.inspect : part}
74
- end
75
52
 
53
+ CLEAR_TO_EOL = "\e[K"
54
+ CLEAR_CURRENT_LINE = "\e[2K"
55
+
56
+
57
+ TAR_OPTS = { :compression => :gzip }
58
+
59
+
60
+ ###############
61
+ module_function
62
+ ###############
63
+
64
+ ### Output a logging message
65
+ def log( *msg )
66
+ output = colorize( msg.flatten.join(' '), 'cyan' )
67
+ $stderr.puts( output )
68
+ end
69
+
70
+
71
+ ### Output a logging message if tracing is on
72
+ def trace( *msg )
73
+ return unless $trace
74
+ output = colorize( msg.flatten.join(' '), 'yellow' )
75
+ $stderr.puts( output )
76
+ end
76
77
 
77
- ### Run the specified command +cmd+ with system(), failing if the execution
78
- ### fails.
79
- def run( *cmd )
80
- cmd.flatten!
81
78
 
82
- if cmd.length > 1
83
- trace( quotelist(*cmd) )
84
- else
85
- trace( cmd )
79
+ ### Return the specified args as a string, quoting any that have a space.
80
+ def quotelist( *args )
81
+ return args.flatten.collect {|part| part =~ /\s/ ? part.inspect : part}
86
82
  end
87
83
 
88
- if $dryrun
89
- $stderr.puts "(dry run mode)"
90
- else
91
- system( *cmd )
92
- unless $?.success?
93
- fail "Command failed: [%s]" % [cmd.join(' ')]
84
+
85
+ ### Run the specified command +cmd+ with system(), failing if the execution
86
+ ### fails.
87
+ def run( *cmd )
88
+ cmd.flatten!
89
+
90
+ if cmd.length > 1
91
+ trace( quotelist(*cmd) )
92
+ else
93
+ trace( cmd )
94
+ end
95
+
96
+ if $dryrun
97
+ $stderr.puts "(dry run mode)"
98
+ else
99
+ system( *cmd )
100
+ unless $?.success?
101
+ fail "Command failed: [%s]" % [cmd.join(' ')]
102
+ end
94
103
  end
95
104
  end
96
- end
97
105
 
98
106
 
99
- ### Run the given +cmd+ with the specified +args+ without interpolation by the shell and
100
- ### return anything written to its STDOUT.
101
- def read_command_output( cmd, *args )
102
- trace "Reading output from: %s" % [ cmd, quotelist(cmd, *args) ]
103
- output = IO.read( '|-' ) or exec cmd, *args
104
- return output
105
- end
107
+ ### Run the given +cmd+ with the specified +args+ without interpolation by the shell and
108
+ ### return anything written to its STDOUT.
109
+ def read_command_output( cmd, *args )
110
+ trace "Reading output from: %s" % [ cmd, quotelist(cmd, *args) ]
111
+ output = IO.read( '|-' ) or exec cmd, *args
112
+ return output
113
+ end
106
114
 
107
115
 
108
- ### Run a subordinate Rake process with the same options and the specified +targets+.
109
- def rake( *targets )
110
- opts = ARGV.select {|arg| arg[0,1] == '-' }
111
- args = opts + targets.map {|t| t.to_s }
112
- run 'rake', '-N', *args
113
- end
116
+ ### Run a subordinate Rake process with the same options and the specified +targets+.
117
+ def rake( *targets )
118
+ opts = ARGV.select {|arg| arg[0,1] == '-' }
119
+ args = opts + targets.map {|t| t.to_s }
120
+ run 'rake', '-N', *args
121
+ end
114
122
 
115
123
 
116
- ### Open a pipe to a process running the given +cmd+ and call the given block with it.
117
- def pipeto( *cmd )
118
- $DEBUG = true
124
+ ### Open a pipe to a process running the given +cmd+ and call the given block with it.
125
+ def pipeto( *cmd )
126
+ $DEBUG = true
119
127
 
120
- cmd.flatten!
121
- log( "Opening a pipe to: ", cmd.collect {|part| part =~ /\s/ ? part.inspect : part} )
122
- if $dryrun
123
- $stderr.puts "(dry run mode)"
124
- else
125
- open( '|-', 'w+' ) do |io|
128
+ cmd.flatten!
129
+ log( "Opening a pipe to: ", cmd.collect {|part| part =~ /\s/ ? part.inspect : part} )
130
+ if $dryrun
131
+ $stderr.puts "(dry run mode)"
132
+ else
133
+ open( '|-', 'w+' ) do |io|
126
134
 
127
- # Parent
128
- if io
129
- yield( io )
135
+ # Parent
136
+ if io
137
+ yield( io )
130
138
 
131
- # Child
132
- else
133
- exec( *cmd )
134
- fail "Command failed: [%s]" % [cmd.join(' ')]
139
+ # Child
140
+ else
141
+ exec( *cmd )
142
+ fail "Command failed: [%s]" % [cmd.join(' ')]
143
+ end
135
144
  end
136
145
  end
137
146
  end
138
- end
139
147
 
140
148
 
141
- ### Download the file at +sourceuri+ via HTTP and write it to +targetfile+.
142
- def download( sourceuri, targetfile=nil )
143
- oldsync = $stdout.sync
144
- $stdout.sync = true
145
- require 'open-uri'
149
+ ### Download the file at +sourceuri+ via HTTP and write it to +targetfile+.
150
+ def download( sourceuri, targetfile=nil )
151
+ oldsync = $stdout.sync
152
+ $stdout.sync = true
153
+ require 'open-uri'
146
154
 
147
- targetpath = Pathname.new( targetfile )
155
+ targetpath = Pathname.new( targetfile )
148
156
 
149
- log "Downloading %s to %s" % [sourceuri, targetfile]
150
- trace " connecting..."
151
- ifh = open( sourceuri ) do |ifh|
152
- trace " connected..."
153
- targetpath.open( File::WRONLY|File::TRUNC|File::CREAT, 0644 ) do |ofh|
154
- log "Downloading..."
155
- buf = ''
157
+ log "Downloading %s to %s" % [sourceuri, targetfile]
158
+ trace " connecting..."
159
+ ifh = open( sourceuri ) do |ifh|
160
+ trace " connected..."
161
+ targetpath.open( File::WRONLY|File::TRUNC|File::CREAT, 0644 ) do |ofh|
162
+ log "Downloading..."
163
+ buf = ''
156
164
 
157
- while ifh.read( 16384, buf )
158
- until buf.empty?
159
- bytes = ofh.write( buf )
160
- buf.slice!( 0, bytes )
165
+ while ifh.read( 16384, buf )
166
+ until buf.empty?
167
+ bytes = ofh.write( buf )
168
+ buf.slice!( 0, bytes )
169
+ end
161
170
  end
171
+
172
+ log "Done."
162
173
  end
163
174
 
164
- log "Done."
165
175
  end
166
176
 
177
+ return targetpath
178
+ ensure
179
+ $stdout.sync = oldsync
167
180
  end
168
181
 
169
- return targetpath
170
- ensure
171
- $stdout.sync = oldsync
172
- end
173
182
 
183
+ ### Return the fully-qualified path to the specified +program+ in the PATH.
184
+ def which( program )
185
+ return nil unless ENV['PATH']
186
+ ENV['PATH'].split(/:/).
187
+ collect {|dir| Pathname.new(dir) + program }.
188
+ find {|path| path.exist? && path.executable? }
189
+ end
174
190
 
175
- ### Return the fully-qualified path to the specified +program+ in the PATH.
176
- def which( program )
177
- return nil unless ENV['PATH']
178
- ENV['PATH'].split(/:/).
179
- collect {|dir| Pathname.new(dir) + program }.
180
- find {|path| path.exist? && path.executable? }
181
- end
182
191
 
192
+ ### Create a string that contains the ANSI codes specified and return it
193
+ def ansi_code( *attributes )
194
+ attributes.flatten!
195
+ attributes.collect! {|at| at.to_s }
196
+ # $stderr.puts "Returning ansicode for TERM = %p: %p" %
197
+ # [ ENV['TERM'], attributes ]
198
+ return '' unless /(?:vt10[03]|xterm(?:-color)?|linux|screen)/i =~ ENV['TERM']
199
+ attributes = ANSI_ATTRIBUTES.values_at( *attributes ).compact.join(';')
183
200
 
184
- ### Create a string that contains the ANSI codes specified and return it
185
- def ansi_code( *attributes )
186
- attributes.flatten!
187
- attributes.collect! {|at| at.to_s }
188
- # $stderr.puts "Returning ansicode for TERM = %p: %p" %
189
- # [ ENV['TERM'], attributes ]
190
- return '' unless /(?:vt10[03]|xterm(?:-color)?|linux|screen)/i =~ ENV['TERM']
191
- attributes = ANSI_ATTRIBUTES.values_at( *attributes ).compact.join(';')
192
-
193
- # $stderr.puts " attr is: %p" % [attributes]
194
- if attributes.empty?
195
- return ''
196
- else
197
- return "\e[%sm" % attributes
201
+ # $stderr.puts " attr is: %p" % [attributes]
202
+ if attributes.empty?
203
+ return ''
204
+ else
205
+ return "\e[%sm" % attributes
206
+ end
198
207
  end
199
- end
200
208
 
201
209
 
202
- ### Colorize the given +string+ with the specified +attributes+ and return it, handling
203
- ### line-endings, color reset, etc.
204
- def colorize( *args )
205
- string = ''
210
+ ### Colorize the given +string+ with the specified +attributes+ and return it, handling
211
+ ### line-endings, color reset, etc.
212
+ def colorize( *args )
213
+ string = ''
214
+
215
+ if block_given?
216
+ string = yield
217
+ else
218
+ string = args.shift
219
+ end
220
+
221
+ ending = string[/(\s)$/] || ''
222
+ string = string.rstrip
206
223
 
207
- if block_given?
208
- string = yield
209
- else
210
- string = args.shift
224
+ return ansi_code( args.flatten ) + string + ansi_code( 'reset' ) + ending
211
225
  end
212
226
 
213
- ending = string[/(\s)$/] || ''
214
- string = string.rstrip
215
227
 
216
- return ansi_code( args.flatten ) + string + ansi_code( 'reset' ) + ending
217
- end
228
+ ### Output the specified <tt>msg</tt> as an ANSI-colored error message
229
+ ### (white on red).
230
+ def error_message( msg, details='' )
231
+ $stderr.puts colorize( 'bold', 'white', 'on_red' ) { msg } + details
232
+ end
233
+ alias :error :error_message
218
234
 
219
235
 
220
- ### Output the specified <tt>msg</tt> as an ANSI-colored error message
221
- ### (white on red).
222
- def error_message( msg, details='' )
223
- $stderr.puts colorize( 'bold', 'white', 'on_red' ) { msg } + details
224
- end
225
- alias :error :error_message
236
+ ### Highlight and embed a prompt control character in the given +string+ and return it.
237
+ def make_prompt_string( string )
238
+ return CLEAR_CURRENT_LINE + colorize( 'bold', 'green' ) { string + ' ' }
239
+ end
226
240
 
227
241
 
228
- ### Highlight and embed a prompt control character in the given +string+ and return it.
229
- def make_prompt_string( string )
230
- return CLEAR_CURRENT_LINE + colorize( 'bold', 'green' ) { string + ' ' }
231
- end
242
+ ### Output the specified <tt>prompt_string</tt> as a prompt (in green) and
243
+ ### return the user's input with leading and trailing spaces removed. If a
244
+ ### test is provided, the prompt will repeat until the test returns true.
245
+ ### An optional failure message can also be passed in.
246
+ def prompt( prompt_string, failure_msg="Try again." ) # :yields: response
247
+ prompt_string.chomp!
248
+ prompt_string << ":" unless /\W$/.match( prompt_string )
249
+ response = nil
250
+
251
+ begin
252
+ prompt = make_prompt_string( prompt_string )
253
+ response = readline( prompt ) || ''
254
+ response.strip!
255
+ if block_given? && ! yield( response )
256
+ error_message( failure_msg + "\n\n" )
257
+ response = nil
258
+ end
259
+ end while response.nil?
232
260
 
261
+ return response
262
+ end
233
263
 
234
- ### Output the specified <tt>prompt_string</tt> as a prompt (in green) and
235
- ### return the user's input with leading and trailing spaces removed. If a
236
- ### test is provided, the prompt will repeat until the test returns true.
237
- ### An optional failure message can also be passed in.
238
- def prompt( prompt_string, failure_msg="Try again." ) # :yields: response
239
- prompt_string.chomp!
240
- prompt_string << ":" unless /\W$/.match( prompt_string )
241
- response = nil
242
-
243
- begin
244
- prompt = make_prompt_string( prompt_string )
245
- response = readline( prompt ) || ''
246
- response.strip!
247
- if block_given? && ! yield( response )
248
- error_message( failure_msg + "\n\n" )
249
- response = nil
250
- end
251
- end while response.nil?
252
264
 
253
- return response
254
- end
265
+ ### Prompt the user with the given <tt>prompt_string</tt> via #prompt,
266
+ ### substituting the given <tt>default</tt> if the user doesn't input
267
+ ### anything. If a test is provided, the prompt will repeat until the test
268
+ ### returns true. An optional failure message can also be passed in.
269
+ def prompt_with_default( prompt_string, default, failure_msg="Try again." )
270
+ response = nil
255
271
 
272
+ begin
273
+ default ||= '~'
274
+ response = prompt( "%s [%s]" % [ prompt_string, default ] )
275
+ response = default.to_s if !response.nil? && response.empty?
256
276
 
257
- ### Prompt the user with the given <tt>prompt_string</tt> via #prompt,
258
- ### substituting the given <tt>default</tt> if the user doesn't input
259
- ### anything. If a test is provided, the prompt will repeat until the test
260
- ### returns true. An optional failure message can also be passed in.
261
- def prompt_with_default( prompt_string, default, failure_msg="Try again." )
262
- response = nil
277
+ trace "Validating response %p" % [ response ]
263
278
 
264
- begin
265
- default ||= '~'
266
- response = prompt( "%s [%s]" % [ prompt_string, default ] )
267
- response = default.to_s if !response.nil? && response.empty?
279
+ # the block is a validator. We need to make sure that the user didn't
280
+ # enter '~', because if they did, it's nil and we should move on. If
281
+ # they didn't, then call the block.
282
+ if block_given? && response != '~' && ! yield( response )
283
+ error_message( failure_msg + "\n\n" )
284
+ response = nil
285
+ end
286
+ end while response.nil?
268
287
 
269
- trace "Validating response %p" % [ response ]
288
+ return nil if response == '~'
289
+ return response
290
+ end
270
291
 
271
- # the block is a validator. We need to make sure that the user didn't
272
- # enter '~', because if they did, it's nil and we should move on. If
273
- # they didn't, then call the block.
274
- if block_given? && response != '~' && ! yield( response )
275
- error_message( failure_msg + "\n\n" )
276
- response = nil
292
+
293
+ ### Prompt for an array of values
294
+ def prompt_for_multiple_values( label, default=nil )
295
+ $stderr.puts( MULTILINE_PROMPT % [label] )
296
+ if default
297
+ $stderr.puts "Enter a single blank line to keep the default:\n %p" % [ default ]
277
298
  end
278
- end while response.nil?
279
299
 
280
- return nil if response == '~'
281
- return response
282
- end
300
+ results = []
301
+ result = nil
283
302
 
303
+ begin
304
+ result = readline( make_prompt_string("> ") )
305
+ if result.nil? || result.empty?
306
+ results << default if default && results.empty?
307
+ else
308
+ results << result
309
+ end
310
+ end until result.nil? || result.empty?
284
311
 
285
- ### Prompt for an array of values
286
- def prompt_for_multiple_values( label, default=nil )
287
- $stderr.puts( MULTILINE_PROMPT % [label] )
288
- if default
289
- $stderr.puts "Enter a single blank line to keep the default:\n %p" % [ default ]
312
+ return results.flatten
290
313
  end
291
314
 
292
- results = []
293
- result = nil
294
315
 
295
- begin
296
- result = readline( make_prompt_string("> ") )
297
- if result.nil? || result.empty?
298
- results << default if default && results.empty?
299
- else
300
- results << result
301
- end
302
- end until result.nil? || result.empty?
316
+ ### Turn echo and masking of input on/off.
317
+ def noecho( masked=false )
318
+ require 'termios'
303
319
 
304
- return results.flatten
305
- end
320
+ rval = nil
321
+ term = Termios.getattr( $stdin )
306
322
 
323
+ begin
324
+ newt = term.dup
325
+ newt.c_lflag &= ~Termios::ECHO
326
+ newt.c_lflag &= ~Termios::ICANON if masked
307
327
 
308
- ### Turn echo and masking of input on/off.
309
- def noecho( masked=false )
310
- require 'termios'
328
+ Termios.tcsetattr( $stdin, Termios::TCSANOW, newt )
311
329
 
312
- rval = nil
313
- term = Termios.getattr( $stdin )
330
+ rval = yield
331
+ ensure
332
+ Termios.tcsetattr( $stdin, Termios::TCSANOW, term )
333
+ end
314
334
 
315
- begin
316
- newt = term.dup
317
- newt.c_lflag &= ~Termios::ECHO
318
- newt.c_lflag &= ~Termios::ICANON if masked
335
+ return rval
336
+ end
319
337
 
320
- Termios.tcsetattr( $stdin, Termios::TCSANOW, newt )
321
338
 
322
- rval = yield
323
- ensure
324
- Termios.tcsetattr( $stdin, Termios::TCSANOW, term )
339
+ ### Prompt the user for her password, turning off echo if the 'termios' module is
340
+ ### available.
341
+ def prompt_for_password( prompt="Password: " )
342
+ return noecho( true ) do
343
+ $stderr.print( prompt )
344
+ ($stdin.gets || '').chomp
345
+ end
325
346
  end
326
347
 
327
- return rval
328
- end
329
348
 
349
+ ### Display a description of a potentially-dangerous task, and prompt
350
+ ### for confirmation. If the user answers with anything that begins
351
+ ### with 'y', yield to the block. If +abort_on_decline+ is +true+,
352
+ ### any non-'y' answer will fail with an error message.
353
+ def ask_for_confirmation( description, abort_on_decline=true )
354
+ puts description
355
+
356
+ answer = prompt_with_default( "Continue?", 'n' ) do |input|
357
+ input =~ /^[yn]/i
358
+ end
359
+
360
+ if answer =~ /^y/i
361
+ return yield
362
+ elsif abort_on_decline
363
+ error "Aborted."
364
+ fail
365
+ end
330
366
 
331
- ### Prompt the user for her password, turning off echo if the 'termios' module is
332
- ### available.
333
- def prompt_for_password( prompt="Password: " )
334
- return noecho( true ) do
335
- $stderr.print( prompt )
336
- ($stdin.gets || '').chomp
367
+ return false
337
368
  end
338
- end
369
+ alias :prompt_for_confirmation :ask_for_confirmation
339
370
 
340
371
 
341
- ### Display a description of a potentially-dangerous task, and prompt
342
- ### for confirmation. If the user answers with anything that begins
343
- ### with 'y', yield to the block. If +abort_on_decline+ is +true+,
344
- ### any non-'y' answer will fail with an error message.
345
- def ask_for_confirmation( description, abort_on_decline=true )
346
- puts description
372
+ ### Search line-by-line in the specified +file+ for the given +regexp+, returning the
373
+ ### first match, or nil if no match was found. If the +regexp+ has any capture groups,
374
+ ### those will be returned in an Array, else the whole matching line is returned.
375
+ def find_pattern_in_file( regexp, file )
376
+ rval = nil
347
377
 
348
- answer = prompt_with_default( "Continue?", 'n' ) do |input|
349
- input =~ /^[yn]/i
350
- end
378
+ File.open( file, 'r' ).each do |line|
379
+ if (( match = regexp.match(line) ))
380
+ rval = match.captures.empty? ? match[0] : match.captures
381
+ break
382
+ end
383
+ end
351
384
 
352
- if answer =~ /^y/i
353
- return yield
354
- elsif abort_on_decline
355
- error "Aborted."
356
- fail
385
+ return rval
357
386
  end
358
387
 
359
- return false
360
- end
361
- alias :prompt_for_confirmation :ask_for_confirmation
362
388
 
389
+ ### Search line-by-line in the output of the specified +cmd+ for the given +regexp+,
390
+ ### returning the first match, or nil if no match was found. If the +regexp+ has any
391
+ ### capture groups, those will be returned in an Array, else the whole matching line
392
+ ### is returned.
393
+ def find_pattern_in_pipe( regexp, *cmd )
394
+ require 'open3'
395
+ output = []
363
396
 
364
- ### Search line-by-line in the specified +file+ for the given +regexp+, returning the
365
- ### first match, or nil if no match was found. If the +regexp+ has any capture groups,
366
- ### those will be returned in an Array, else the whole matching line is returned.
367
- def find_pattern_in_file( regexp, file )
368
- rval = nil
397
+ log( cmd.collect {|part| part =~ /\s/ ? part.inspect : part} )
398
+ Open3.popen3( *cmd ) do |stdin, stdout, stderr|
399
+ stdin.close
369
400
 
370
- File.open( file, 'r' ).each do |line|
371
- if (( match = regexp.match(line) ))
372
- rval = match.captures.empty? ? match[0] : match.captures
373
- break
401
+ output << stdout.gets until stdout.eof?
402
+ output << stderr.gets until stderr.eof?
374
403
  end
375
- end
376
404
 
377
- return rval
378
- end
405
+ result = output.find { |line| regexp.match(line) }
406
+ return $1 || result
407
+ end
379
408
 
380
409
 
381
- ### Search line-by-line in the output of the specified +cmd+ for the given +regexp+,
382
- ### returning the first match, or nil if no match was found. If the +regexp+ has any
383
- ### capture groups, those will be returned in an Array, else the whole matching line
384
- ### is returned.
385
- def find_pattern_in_pipe( regexp, *cmd )
386
- output = []
410
+ ### Invoke the user's editor on the given +filename+ and return the exit code
411
+ ### from doing so.
412
+ def edit( filename )
413
+ editor = ENV['EDITOR'] || ENV['VISUAL'] || DEFAULT_EDITOR
414
+ system editor, filename
415
+ unless $?.success? || editor =~ /vim/i
416
+ fail "Editor exited uncleanly."
417
+ end
418
+ end
387
419
 
388
- log( cmd.collect {|part| part =~ /\s/ ? part.inspect : part} )
389
- Open3.popen3( *cmd ) do |stdin, stdout, stderr|
390
- stdin.close
391
420
 
392
- output << stdout.gets until stdout.eof?
393
- output << stderr.gets until stderr.eof?
421
+ ### Extract all the non Rake-target arguments from ARGV and return them.
422
+ def get_target_args
423
+ args = ARGV.reject {|arg| arg =~ /^-/ || Rake::Task.task_defined?(arg) }
424
+ return args
394
425
  end
395
426
 
396
- result = output.find { |line| regexp.match(line) }
397
- return $1 || result
398
- end
399
427
 
428
+ ### Log a subdirectory change, execute a block, and exit the subdirectory
429
+ def in_subdirectory( subdir )
430
+ block = Proc.new
400
431
 
401
- ### Invoke the user's editor on the given +filename+ and return the exit code
402
- ### from doing so.
403
- def edit( filename )
404
- editor = ENV['EDITOR'] || ENV['VISUAL'] || DEFAULT_EDITOR
405
- system editor, filename
406
- unless $?.success? || editor =~ /vim/i
407
- fail "Editor exited uncleanly."
432
+ log "Entering #{subdir}"
433
+ Dir.chdir( subdir, &block )
434
+ log "Leaving #{subdir}"
408
435
  end
409
- end
410
436
 
411
437
 
412
- ### Extract all the non Rake-target arguments from ARGV and return them.
413
- def get_target_args
414
- args = ARGV.reject {|arg| arg =~ /^-/ || Rake::Task.task_defined?(arg) }
415
- return args
416
- end
438
+ ### Make an easily-comparable version vector out of +ver+ and return it.
439
+ def vvec( ver )
440
+ return ver.split('.').collect {|char| char.to_i }.pack('N*')
441
+ end
417
442
 
418
443
 
419
- ### Log a subdirectory change, execute a block, and exit the subdirectory
420
- def in_subdirectory( subdir )
421
- block = Proc.new
444
+ ### Archive::Tar::Reader#extract (as of 0.9.0) is broken w.r.t.
445
+ ### permissions, so we have to do this ourselves.
446
+ def untar( tarfile, targetdir )
447
+ require 'archive/tar'
448
+ targetdir = Pathname( targetdir )
449
+ raise "No such directory: #{targetdir}" unless targetdir.directory?
422
450
 
423
- log "Entering #{subdir}"
424
- Dir.chdir( subdir, &block )
425
- log "Leaving #{subdir}"
426
- end
451
+ reader = Archive::Tar::Reader.new( tarfile.to_s, TAR_OPTS )
427
452
 
453
+ mkdir_p( targetdir )
454
+ reader.each( true ) do |header, body|
455
+ path = targetdir + header[:path]
456
+ # trace "Header is: %p" % [ header ]
428
457
 
429
- ### Make an easily-comparable version vector out of +ver+ and return it.
430
- def vvec( ver )
431
- return ver.split('.').collect {|char| char.to_i }.pack('N*')
432
- end
458
+ case header[:type]
459
+ when :file
460
+ trace " #{path}"
461
+ path.open( File::WRONLY|File::EXCL|File::CREAT|File::TRUNC, header[:mode] ) do |fio|
462
+ bytesize = header[:size]
463
+ fio.write( body[0,bytesize] )
464
+ end
465
+
466
+ when :directory
467
+ trace " #{path}"
468
+ path.mkpath
469
+
470
+ when :link
471
+ linktarget = targetdir + header[:dest]
472
+ trace " #{path} => #{linktarget}"
473
+ path.make_link( linktarget.to_s )
474
+
475
+ when :symlink
476
+ linktarget = targetdir + header[:dest]
477
+ trace " #{path} -> #{linktarget}"
478
+ path.make_symlink( linktarget )
479
+ end
480
+ end
481
+
482
+ end
483
+
484
+
485
+ ### Extract the contents of the specified +zipfile+ into the given +targetdir+.
486
+ def unzip( zipfile, targetdir, *files )
487
+ require 'zip/zip'
488
+ targetdir = Pathname( targetdir )
489
+ raise "No such directory: #{targetdir}" unless targetdir.directory?
490
+
491
+ Zip::ZipFile.foreach( zipfile ) do |entry|
492
+ # trace " entry is: %p" % [ entry ]
493
+ next unless files.empty? || files.include?( entry.name )
494
+ target_path = targetdir + entry.name
495
+ # trace " would extract to: %s" % [ target_path ]
496
+ entry.extract( target_path ) { true }
497
+ end
498
+ end
433
499
 
500
+ end # module Rakefile::Helpers
434
501
 
435
502