bitgirder-platform 0.1.7 → 0.1.10

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.
data/bin/install-mysql CHANGED
@@ -176,14 +176,18 @@ class App < BitGirderClass
176
176
 
177
177
  private
178
178
  def update_root_accounts( db )
179
-
180
- sql = <<-SQL
181
- update mysql.user
182
- set password = password( '#{db.escape_string( root_pass() )}' )
183
- where user = 'root'
184
- SQL
185
179
 
186
- db.query( sql )
180
+ ru = db.escape_string( root_user )
181
+ rp = db.escape_string( root_pass )
182
+
183
+ db.query( "delete from mysql.user where user = 'root'" )
184
+ db.query( "flush privileges" )
185
+
186
+ db.query <<-SQL
187
+ grant all on *.* to '#{ru}'@'localhost' identified by '#{rp}'
188
+ with grant option
189
+ SQL
190
+
187
191
  db.query( "flush privileges" )
188
192
  end
189
193
 
@@ -224,15 +228,16 @@ class App < BitGirderClass
224
228
  set_root_pass( opts )
225
229
 
226
230
  # Now re-connect with pass (to verify that previous step worked)
227
- opts.merge!( password: root_pass() )
231
+ opts.merge!( user: root_user(), password: root_pass() )
228
232
  secure_db_install( opts )
229
233
  end
230
234
 
231
235
  private
232
- def stop_db( pid, with_pass )
236
+ def stop_db( pid, with_defaults )
233
237
 
234
- argv = [ "--defaults-file=#{my_cnf()}", "-u", "root" ]
235
- argv << "--password=#{root_pass()}" if with_pass
238
+ u = with_defaults ? "root" : root_user
239
+ argv = [ "--defaults-file=#{my_cnf()}", "-u", "#{u}" ]
240
+ argv << "--password=#{root_pass()}" unless with_defaults
236
241
  argv << "shutdown"
237
242
 
238
243
  UnixProcessBuilder.new( cmd: mysqladmin(), argv: argv ).system
@@ -252,7 +257,7 @@ class App < BitGirderClass
252
257
  run_db_init
253
258
  init_done = true
254
259
  ensure
255
- stop_db( pid, init_done )
260
+ stop_db( pid, ! init_done )
256
261
  end
257
262
  end
258
263
 
@@ -293,7 +298,11 @@ class App < BitGirderClass
293
298
  io.print <<-END
294
299
  #!#{bash()}
295
300
 
296
- exec #{mysqladmin()} --defaults-file=#{my_cnf()} -u #{root_user()} "$@"
301
+ exec #{mysqladmin()} \
302
+ --defaults-file=#{my_cnf()} \
303
+ -u #{root_user()} \
304
+ -p#{root_pass()} \
305
+ "$@"
297
306
  END
298
307
  end
299
308
  end
data/bin/tomcat7 CHANGED
@@ -8,75 +8,27 @@ require 'bitgirder/io'
8
8
  require 'bitgirder/ops/java'
9
9
  include BitGirder::Ops::Java
10
10
 
11
- require 'mingle'
12
- include Mingle
13
-
14
- require 'mingle/json'
15
-
16
11
  require 'rexml/document'
17
12
 
18
13
  require 'socket'
19
14
 
20
- ENV_TOMCAT7_HOME = "TOMCAT7_HOME"
15
+ ENV_TOMCAT7_RUNTIME = "TOMCAT7_RUNTIME"
21
16
 
22
17
  class Command < BitGirderClass
23
18
 
24
19
  include BitGirder::Io
25
20
 
26
- private
27
- def load_struct( f )
28
-
29
- File.open( f ) do |io|
30
- Mingle::Json::JsonMingleCodec.new.from_buffer( io.read( io.size ) )
31
- end
32
- end
33
-
34
- private
35
- def save_struct( f, s )
36
-
37
- File.open( ensure_parent( f ), "w" ) do |io|
38
- io.print Mingle::Json::JsonMingleCodec.new.as_buffer( s )
39
- end
40
- end
41
-
42
21
  private
43
22
  def load_config( f )
44
-
45
- flds = load_struct( f ).fields
46
-
47
- TomcatConfig.new(
48
- control_port: flds.expect_int( :control_port ),
49
- http_port: flds.expect_int( :http_port ),
50
- https_port: flds.expect_int( :https_port ),
51
- shutdown_string: flds.expect_string( :shutdown_string ),
52
- tomcat_home: flds.expect_string( :tomcat_home ),
53
- java_home: flds.expect_string( :java_home )
54
- )
55
- end
56
-
57
- private
58
- def load_runtime_config( rt )
59
- load_config( "#{rt}/config.json" )
60
- end
61
- end
62
-
63
- class Help < Command
64
-
65
- public
66
- def run( run_ctx )
67
-
68
- print "\ncommands:\n\n"
69
- COMMANDS.keys.sort.each { |s| puts "#{ " " * 4 }#{s}" }
70
- puts
71
-
23
+ load_yaml( f )
72
24
  end
73
25
  end
74
26
 
75
27
  class TomcatConfig < BitGirderClass
76
28
 
77
29
  bg_attr :control_port, validation: :positive
78
- bg_attr :http_port, validation: :positive
79
- bg_attr :https_port, validation: :positive
30
+ bg_attr :http_port, validation: :positive, required: false
31
+ bg_attr :https_port, validation: :positive, required: false
80
32
 
81
33
  bg_attr :shutdown_string
82
34
 
@@ -86,67 +38,29 @@ class TomcatConfig < BitGirderClass
86
38
  validation: :file_exists,
87
39
  default: lambda { JavaEnvironments.get_java_home }
88
40
 
89
- public
90
- def to_mingle_struct
91
-
92
- MingleStruct.new(
93
- type: :"bitgirder:ops:tomcat@v1/TomcatConfig",
94
- fields: {
95
- control_port: @control_port,
96
- http_port: @http_port,
97
- https_port: @https_port,
98
- shutdown_string: @shutdown_string,
99
- tomcat_home: @tomcat_home,
100
- java_home: @java_home
101
- }
102
- )
103
- end
41
+ bg_attr :sysprops, default: lambda { {} }
42
+
43
+ bg_attr :classpath_dirs, default: lambda { [] }
104
44
  end
105
45
 
106
46
  PORT_OPTS = { validation: :positive, processor: :integer }
107
47
 
48
+ def tomcat7_dir( base )
49
+ "#{base}/tomcat7"
50
+ end
51
+
108
52
  class Install < Command
109
53
 
110
54
  PROTO_HTTP11 = "HTTP/1.1"
111
55
 
112
56
  bg_attr :install_to
113
57
 
58
+ bg_attr :install_opts, validation: :file_exists
59
+
114
60
  bg_attr :tomcat_home, validation: :file_exists
115
61
 
116
- bg_attr :control_port, PORT_OPTS
117
-
118
- bg_attr :http_port, PORT_OPTS
119
-
120
- bg_attr :https_port, PORT_OPTS.merge( required: false )
121
-
122
- bg_attr :ssl_keystore, validation: :file_exists, required: false
123
-
124
- bg_attr :ssl_keystore_pass, required: false
125
-
126
- bg_attr :ssl_keystore_type, required: false
127
-
128
- bg_attr :ssl_key_alias, required: false
129
-
130
- bg_attr :ssl_key_pass, required: false
131
-
132
62
  bg_attr :wipe_install, required: false, processor: :boolean
133
63
 
134
- bg_attr :webapps,
135
- is_list: true,
136
- processor: lambda { |s|
137
- idx = s.index( "=" ) || s.size
138
- dest = s[ 0, idx ]
139
- if idx < s.size - 1
140
- [ dest, s[ idx + 1 .. -1 ] ]
141
- else
142
- raise "Need a name for webapp #{dest}"
143
- end
144
- },
145
- list_validation: :not_empty
146
-
147
- bg_attr :java_home,
148
- default: lambda { JavaEnvironments.get_java_home }
149
-
150
64
  private
151
65
  def impl_initialize
152
66
 
@@ -161,20 +75,50 @@ class Install < Command
161
75
 
162
76
  private
163
77
  def base_dir( dir )
164
- "#@install_to/catalina/#{dir}"
78
+ "#{tomcat7_dir( @install_to )}/#{dir}"
165
79
  end
166
80
 
81
+ # Scoped to its own method to reduce risk of local vars in eval'd code
82
+ # stomping on something in this script
167
83
  private
168
- def init_config
84
+ def eval_install_opts
85
+ eval( IO::read( @install_opts ), binding, @install_opts )
86
+ end
169
87
 
170
- @config = TomcatConfig.new(
171
- control_port: @control_port,
172
- http_port: @http_port,
173
- https_port: @https_port,
88
+ private
89
+ def load_install_opts
90
+
91
+ case @install_opts
92
+ when /\.rb$/ then eval_install_opts
93
+ when /\.yaml$/ then load_yaml( @install_opts )
94
+ else raise "Unhandled install opts: #@install_opts"
95
+ end
96
+ end
97
+
98
+ private
99
+ def expect_install_opt( opts, key )
100
+
101
+ opts[ key ] or raise "No value in install opts for #{key.inspect}"
102
+ end
103
+
104
+ private
105
+ def init_config( tc_opts )
106
+
107
+ defls = {
174
108
  shutdown_string: rand( 2 ** 128 ).to_s( 16 ),
175
- tomcat_home: @tomcat_home,
176
- java_home: @java_home
177
- )
109
+ tomcat_home: @tomcat_home
110
+ }
111
+
112
+ @config = TomcatConfig.new( defls.merge( tc_opts ) )
113
+ end
114
+
115
+ private
116
+ def process_install_opts
117
+
118
+ opts = load_install_opts
119
+ init_config( expect_install_opt( opts, :tomcat_opts ) )
120
+ @webapps = expect_install_opt( opts, :webapps )
121
+ @ssl_opts = opts[ :ssl_opts ] || {}
178
122
  end
179
123
 
180
124
  private
@@ -232,7 +176,7 @@ class Install < Command
232
176
  private
233
177
  def add_https_connector( svc )
234
178
 
235
- svc << new_elt( :Connector,
179
+ attrs = {
236
180
  :port => @config.https_port,
237
181
  :protocol => PROTO_HTTP11,
238
182
  :SSLEnabled => true,
@@ -240,13 +184,12 @@ class Install < Command
240
184
  :scheme => "https",
241
185
  :secure => true,
242
186
  :clientAuth => false,
243
- :sslProtocol => :TLS,
244
- :keystoreFile => @ssl_keystore,
245
- :keystorePass => @ssl_keystore_pass,
246
- :keystoreType => @ssl_keystore_type,
247
- :keyAlias => @ssl_key_alias,
248
- :keyPass => @ssl_key_pass
249
- )
187
+ :sslProtocol => :TLS
188
+ }
189
+
190
+ attrs.merge!( @ssl_opts )
191
+
192
+ svc << new_elt( :Connector, attrs )
250
193
  end
251
194
 
252
195
  private
@@ -279,8 +222,8 @@ class Install < Command
279
222
 
280
223
  doc.root << ( svc = new_elt( :Service, :name => "Catalina" ) )
281
224
 
282
- add_http_connector( svc )
283
- add_https_connector( svc )
225
+ add_http_connector( svc ) if @config.http_port
226
+ add_https_connector( svc ) if @config.https_port
284
227
 
285
228
  add_engine( svc )
286
229
  end
@@ -317,7 +260,7 @@ class Install < Command
317
260
  def install_webapps
318
261
 
319
262
  @webapps.each do |app|
320
-
263
+
321
264
  dest, src = *app
322
265
  dest = ensure_parent( dest )
323
266
  fu().ln_s( src, "#{base_dir( :webapps )}/#{dest}" )
@@ -326,23 +269,41 @@ class Install < Command
326
269
 
327
270
  private
328
271
  def write_config
329
- save_struct( "#@install_to/config.json", @config.to_mingle_struct )
272
+ dump_yaml( @config, "#@install_to/config.yaml" )
273
+ end
274
+
275
+ private
276
+ def write_logging_properties
277
+
278
+ File.open( "#{base_dir( :conf )}/logging.properties", "w" ) do |io|
279
+
280
+ io.print <<-END_LOGGING
281
+ handlers = java.util.logging.ConsoleHandler
282
+ .handlers = java.util.logging.ConsoleHandler
283
+ java.util.logging.ConsoleHandler.level = FINE
284
+ java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter
285
+ org.apache.catalina.core.ContainerBase.[Catalina].[localhost].level = INFO
286
+ org.apache.catalina.core.ContainerBase.[Catalina].[localhost].handlers = java.util.logging.ConsoleHandler
287
+ END_LOGGING
288
+ end
330
289
  end
331
290
 
332
291
  public
333
292
  def run
334
293
 
335
- init_config
294
+ process_install_opts
336
295
  setup_install_dir
337
296
  write_server_conf
338
297
  install_webapps
339
298
  write_config
299
+ write_logging_properties
340
300
  end
341
301
  end
342
302
 
343
303
  class TomcatProcessBuilder < BitGirderClass
344
304
 
345
305
  bg_attr :runtime
306
+
346
307
  bg_attr :config
347
308
 
348
309
  bg_attr :proc_opts, default: lambda { {} }
@@ -351,30 +312,42 @@ class TomcatProcessBuilder < BitGirderClass
351
312
 
352
313
  private
353
314
  def get_run_classpath
354
-
355
- %w{ bootstrap.jar tomcat-juli.jar }.map do |f|
315
+
316
+ res = %w{ bootstrap.jar tomcat-juli.jar }.map do |f|
356
317
  file_exists( "#{@config.tomcat_home}/bin/#{f}" )
357
318
  end
319
+
320
+ res += @config.classpath_dirs
321
+
322
+ res
323
+ end
324
+
325
+ private
326
+ def get_config_sysprops
327
+ {}
358
328
  end
359
329
 
360
330
  private
361
331
  def get_run_sysprops
362
332
 
363
333
  cat_home = @config.tomcat_home
334
+ cat_base = tomcat7_dir( @runtime )
364
335
 
365
336
  res = {
366
337
 
367
338
  "java.util.logging.config.file" =>
368
- file_exists( "#{cat_home}/conf/logging.properties" ),
339
+ file_exists( "#{cat_base}/conf/logging.properties" ),
369
340
 
370
341
  "java.util.logging.manager" =>
371
342
  "org.apache.juli.ClassLoaderLogManager",
372
343
 
373
- "catalina.base" => "#@runtime/catalina",
344
+ "catalina.base" => cat_base,
374
345
  "catalina.home" => cat_home,
375
346
 
376
- "java.io.tmpdir" => file_exists( "#@runtime/catalina/temp" )
347
+ "java.io.tmpdir" => file_exists( "#{cat_base}/temp" )
377
348
  }
349
+
350
+ res.merge( @config.sysprops )
378
351
  end
379
352
 
380
353
  private
@@ -402,13 +375,21 @@ class RuntimeCommand < Command
402
375
 
403
376
  bg_attr :runtime,
404
377
  validation: :file_exists,
405
- default: ENV[ ENV_TOMCAT7_HOME ]
378
+ processor: :expand_path,
379
+ required: true, # Since our default may still return nil
380
+ default: lambda {
381
+ if ( v = ( ENV[ ENV_TOMCAT7_RUNTIME ] || "" ).strip ).empty?
382
+ nil
383
+ else
384
+ v
385
+ end
386
+ }
406
387
 
407
388
  include BitGirder::Io
408
389
 
409
390
  private
410
391
  def impl_initialize
411
- @config = load_config( file_exists( "#@runtime/config.json" ) )
392
+ @config = load_config( file_exists( "#@runtime/config.yaml" ) )
412
393
  end
413
394
 
414
395
  private
@@ -432,19 +413,52 @@ end
432
413
  class Daemon < RuntimeCommand
433
414
 
434
415
  private
435
- def do_start
436
-
437
- b = TomcatProcessBuilder.new( config: @config, runtime: @runtime )
416
+ def exec_daemon( b )
438
417
 
439
418
  Process.daemon
419
+
440
420
  File.open( pid_file, "w" ) { |io| io.puts $$ }
441
421
 
442
- out = "#@runtime/catalina/logs/catalina.out"
422
+ out = "#{tomcat7_dir( @runtime )}/logs/catalina.out"
423
+ code( "Sending daemon output to #{out}" )
443
424
  b.proc_opts[ [ STDOUT, STDERR ] ] = File.open( out, "a" )
444
425
 
445
426
  b.build.exec
446
427
  end
447
428
 
429
+ private
430
+ def await_start
431
+
432
+ connected = 4.times.find do |i|
433
+ begin
434
+ TCPSocket::new( "localhost", @config.control_port ).close
435
+ true
436
+ rescue Errno::ECONNREFUSED
437
+ code( "Server ctl port not up yet; waiting" )
438
+ sleep( 2 ** i )
439
+ false
440
+ end
441
+ end
442
+
443
+ raise "Could not get a ctl port connection" unless connected
444
+ end
445
+
446
+ private
447
+ def do_start
448
+
449
+ b = TomcatProcessBuilder.new( config: @config, runtime: @runtime )
450
+
451
+ if File.exist?( pid_file )
452
+ raise "Tomcat already running (or stale pid file #{pid_file})"
453
+ end
454
+
455
+ if fork
456
+ await_start
457
+ else
458
+ exec_daemon( b )
459
+ end
460
+ end
461
+
448
462
  private
449
463
  def get_current_pid
450
464
 
@@ -490,9 +504,13 @@ class Daemon < RuntimeCommand
490
504
  private
491
505
  def await_srv_close
492
506
 
507
+ to_check = [ @config.control_port ]
508
+ to_check << @config.http_port if @config.http_port
509
+ to_check << @config.https_port if @config.https_port
510
+
493
511
  # Returns true if and only if all ports are seen closed
494
- ! [ :control_port, :http_port, :https_port ].find do |port|
495
- ! await_port_close( @config.send( port ) )
512
+ ! to_check.find do |port|
513
+ ! await_port_close( port )
496
514
  end
497
515
  end
498
516
 
@@ -517,13 +535,20 @@ class Daemon < RuntimeCommand
517
535
  do_stop
518
536
  do_start
519
537
  end
538
+
539
+ private
540
+ def do_wipe_pid
541
+
542
+ fu().rm( pid_file ) if File.exist?( pid_file )
543
+ end
520
544
 
521
545
  public
522
546
  def run( run_ctx )
523
547
 
524
548
  cmd = run_ctx[ :argv_remain ].shift or raise "Need a daemon command"
549
+ meth = :"do_#{cmd.gsub( "-", "_" )}"
525
550
 
526
- if respond_to?( meth = :"do_#{cmd}", true )
551
+ if respond_to?( meth, true )
527
552
  send( meth )
528
553
  else
529
554
  raise "Unknown daemon command: #{cmd}"
@@ -538,7 +563,7 @@ class Tailf < RuntimeCommand
538
563
 
539
564
  UnixProcessBuilder.new(
540
565
  cmd: "tail",
541
- argv: [ "-f" ] + Dir.glob( "#@runtime/catalina/logs/*" )
566
+ argv: [ "-f" ] + Dir.glob( "#{tomcat7_dir( @runtime )}/logs/*" )
542
567
  ).
543
568
  exec
544
569
  end
@@ -548,22 +573,7 @@ COMMANDS = {
548
573
  install: Install,
549
574
  run: Run,
550
575
  daemon: Daemon,
551
- tailf: Tailf,
552
- help: Help
576
+ tailf: Tailf
553
577
  }
554
578
 
555
- def get_command_cls
556
-
557
- idx = ARGV.find_index { |arg| ! arg.start_with?( "-" ) }
558
-
559
- cmd_sym = idx ? ARGV.delete_at( idx ).to_sym : :help
560
-
561
- unless res = COMMANDS[ cmd_sym ]
562
- res = Help
563
- STDERR.puts( "Unrecognized command: #{cmd_sym}" )
564
- end
565
-
566
- res
567
- end
568
-
569
- BitGirderCliApplication.run( get_command_cls )
579
+ BitGirderCliApplication.run_subcommand_app( commands: COMMANDS )
@@ -407,7 +407,9 @@ class BitGirderAttribute
407
407
 
408
408
  include BitGirderMethods
409
409
 
410
- class InvalidModifier < RuntimeError; end
410
+ class AttributeError < RuntimeError; end
411
+ class InvalidModifier < AttributeError; end
412
+ class RedefinitionError < AttributeError; end
411
413
 
412
414
  PROCESSOR_BOOLEAN = lambda { |v| BitGirderMethods.to_bool( v ) }
413
415
 
@@ -421,6 +423,8 @@ class BitGirderAttribute
421
423
  # See PROCESSOR_INTEGER
422
424
  PROCESSOR_FLOAT = lambda { |v| v == nil ? nil : v.to_f }
423
425
 
426
+ PROCESSOR_EXPAND_PATH = lambda { |v| File.expand_path( v ) }
427
+
424
428
  VALIDATION_NOT_NIL = lambda { |val| raise "Missing value" if val == nil }
425
429
 
426
430
  # Implies not nil
@@ -482,10 +486,12 @@ class BitGirderAttribute
482
486
  def get_processor( p )
483
487
 
484
488
  case p
489
+ when nil, Proc then p
485
490
  when :boolean then PROCESSOR_BOOLEAN
486
491
  when :symbol then PROCESSOR_SYMBOL
487
492
  when :integer then PROCESSOR_INTEGER
488
493
  when :float then PROCESSOR_FLOAT
494
+ when :expand_path then PROCESSOR_EXPAND_PATH
489
495
 
490
496
  when Class
491
497
  if p.ancestors.include?( BitGirderClass )
@@ -494,7 +500,7 @@ class BitGirderAttribute
494
500
  raise ArgumentError, "Not a #{BitGirderClass}: #{p}"
495
501
  end
496
502
 
497
- else p
503
+ else raise "Unrecognized processor: #{p}"
498
504
  end
499
505
  end
500
506
 
@@ -556,18 +562,29 @@ class BitGirderClassDefinition
556
562
  instance_variable_set( :"@#{attr}", val )
557
563
  end
558
564
  end
559
-
560
- public
561
- def add_attr( opts )
562
565
 
563
- unless opts.key?( :required ) || opts.key?( :default )
564
- opts[ :required ] = true
566
+ private
567
+ def read_add_attr_arg( arg )
568
+
569
+ case arg
570
+ when BitGirderAttribute then arg
571
+ when Hash
572
+ unless arg.key?( :required ) || arg.key?( :default )
573
+ arg[ :required ] = true
574
+ end
575
+ BitGirderAttribute.new( arg )
576
+ else raise "Don't know how to add as attr: #{arg}"
565
577
  end
578
+ end
579
+
580
+ public
581
+ def add_attr( arg )
566
582
 
567
- attr = BitGirderAttribute.new( opts )
583
+ attr = read_add_attr_arg( arg )
568
584
 
569
585
  if @attrs.key?( attr.identifier )
570
- raise "Attribute #{attr.identifier.inspect} already defined"
586
+ msg = "Attribute #{attr.identifier.inspect} already defined"
587
+ raise BitGirderAttribute::RedefinitionError, msg
571
588
  else
572
589
  ident = attr.identifier
573
590
  @attrs[ ident ] = attr
@@ -976,6 +993,7 @@ class BitGirderCliApplication < BitGirderClass
976
993
  # attr.default could be the boolean false, which we still want to
977
994
  # display
978
995
  unless ( defl = attr.default ) == nil
996
+ defl = defl.call if defl.is_a?( Proc )
979
997
  desc += " (Default: #{default_to_s( defl )})"
980
998
  end
981
999
 
@@ -1110,6 +1128,74 @@ class BitGirderCliApplication < BitGirderClass
1110
1128
  BitGirderMethods::not_nil( cls, :cls )
1111
1129
  self.new( :app_class => cls ).run( ARGV )
1112
1130
  end
1131
+
1132
+ class UnrecognizedSubcommandError < StandardError; end
1133
+
1134
+ def self.get_subcommand( commands )
1135
+
1136
+ idx = ARGV.find_index { |arg| ! arg.start_with?( "-" ) }
1137
+
1138
+ return nil unless idx
1139
+
1140
+ cmd_str = ARGV.delete_at( idx )
1141
+ cmd_sym = cmd_str.gsub( "-", "_" ).to_sym
1142
+
1143
+ unless res = commands[ cmd_sym ]
1144
+ raise UnrecognizedSubcommandError, cmd_str
1145
+ end
1146
+
1147
+ res
1148
+ end
1149
+
1150
+ def self.show_subcommand_help( cmds )
1151
+
1152
+ print "\ncommands:\n\n"
1153
+
1154
+ cmds.keys.sort.map { |s| s.to_s.gsub( "_", "-" ) }.
1155
+ each { |s| puts "#{ " " * 4 }#{s}" }
1156
+
1157
+ puts
1158
+ end
1159
+
1160
+ def self.run_subcommand_app( opts )
1161
+
1162
+ cmds = has_key( opts, :commands )
1163
+
1164
+ cmd_cls = begin
1165
+ self.get_subcommand( cmds )
1166
+ rescue UnrecognizedSubcommandError => e
1167
+ STDERR.puts( "Unrecognized command: #{e}" )
1168
+ end
1169
+
1170
+ if cmd_cls
1171
+ self.run( cmd_cls )
1172
+ else
1173
+ self.show_subcommand_help( cmds )
1174
+ end
1175
+ end
1176
+ end
1177
+
1178
+ class AbstractApplication < BitGirderClass
1179
+
1180
+ bg_abstract :impl_run
1181
+
1182
+ attr_reader :run_ctx, :argv_remain
1183
+ attr_accessor :verbose
1184
+
1185
+ public
1186
+ def verbose?
1187
+ @verbose
1188
+ end
1189
+
1190
+ public
1191
+ def run( run_ctx )
1192
+
1193
+ @run_ctx = run_ctx
1194
+ @argv_remain = run_ctx[ :argv_remain ] || []
1195
+ @verbose = run_ctx[ :verbose ]
1196
+
1197
+ impl_run
1198
+ end
1113
1199
  end
1114
1200
 
1115
1201
  class ObjectPath
data/lib/bitgirder/io.rb CHANGED
@@ -168,7 +168,7 @@ def as_write_dest( obj )
168
168
  not_nil( obj, :obj )
169
169
 
170
170
  case obj
171
- when IO, Tempfile then yield( io )
171
+ when IO, Tempfile then yield( obj )
172
172
  when String then File.open( obj, "w" ) { |io| yield( io ) }
173
173
  else raise TypeError, "Unknown write dest: #{obj.class}"
174
174
  end
@@ -953,6 +953,12 @@ class UnixProcessBuilder < BitGirderClass
953
953
  IO.popen( get_call_argv18.join( " " ), mode, &blk )
954
954
  end
955
955
  end
956
+
957
+ [ :spawn, :exec, :system, :popen ].each do |meth|
958
+ self.class.send( :define_method, meth ) { |opts|
959
+ self.new( opts ).send( meth )
960
+ }
961
+ end
956
962
  end
957
963
 
958
964
  end
data/lib/doc-gen17.rb CHANGED
@@ -1,14 +0,0 @@
1
-
2
- # Autogenerated docs on 2012-11-21 11:47:21 -0800
3
- #
4
-
5
- # This code is only included for rdoc purposes and would not normally get
6
- # required. Even so, in case of overzealous scripts which might auto-require
7
- # this file, we enclose the entire body of this file in a guard that will
8
- # prevent it from being interpreted in an actual run
9
- #
10
- if false
11
-
12
-
13
- end # 'if false...' block
14
-
data/lib/doc-gen18.rb CHANGED
@@ -0,0 +1,14 @@
1
+
2
+ # Autogenerated docs on 2012-12-04 17:20:26 -0800
3
+ #
4
+
5
+ # This code is only included for rdoc purposes and would not normally get
6
+ # required. Even so, in case of overzealous scripts which might auto-require
7
+ # this file, we enclose the entire body of this file in a guard that will
8
+ # prevent it from being interpreted in an actual run
9
+ #
10
+ if false
11
+
12
+
13
+ end # 'if false...' block
14
+
data/lib/doc-gen20.rb CHANGED
@@ -1,5 +1,5 @@
1
1
 
2
- # Autogenerated docs on 2012-11-21 11:47:21 -0800
2
+ # Autogenerated docs on 2012-12-04 17:20:26 -0800
3
3
  #
4
4
 
5
5
  # This code is only included for rdoc purposes and would not normally get
data/lib/mingle.rb CHANGED
@@ -332,8 +332,8 @@ class MingleTimestamp < MingleValue
332
332
  new( Time.at( secs ), false )
333
333
  end
334
334
 
335
- # Impl :note => simply calling Time.at( ms / 1000.0 ) doesn't work as we might
336
- # want, since it ends up passing a Float to Time.at() which apparently
335
+ # Impl :note => simply calling Time.at( ms / 1000.0 ) doesn't work as we
336
+ # might want, since it ends up passing a Float to Time.at() which apparently
337
337
  # performs more calculations or otherwise leads to a time which is close to
338
338
  # but not precisely the result of the division. To illustrate:
339
339
  #
@@ -1474,6 +1474,17 @@ class MingleParser < BitGirderClass
1474
1474
  end
1475
1475
  end
1476
1476
 
1477
+ private
1478
+ def exec_cast( ms, typ )
1479
+
1480
+ begin
1481
+ Mingle.cast_value( MingleString.new( ms ), typ )
1482
+ rescue MingleTimestamp::Rfc3339FormatError => e
1483
+ e = RestrictionTypeError.new( e.message ) if typ == TYPE_TIMESTAMP
1484
+ raise e
1485
+ end
1486
+ end
1487
+
1477
1488
  private
1478
1489
  def cast_range_value( val, nm, bound )
1479
1490
 
@@ -1490,7 +1501,7 @@ class MingleParser < BitGirderClass
1490
1501
  # s is a StringToken or a ParsedNumber
1491
1502
  s = val.is_a?( StringToken ) ? val.val : val.external_form
1492
1503
 
1493
- Mingle.cast_value( MingleString.new( s ), typ )
1504
+ exec_cast( MingleString.new( s ), typ )
1494
1505
  end
1495
1506
 
1496
1507
  private
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: bitgirder-platform
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.7
4
+ version: 0.1.10
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-11-21 00:00:00.000000000 Z
12
+ date: 2012-12-05 00:00:00.000000000 Z
13
13
  dependencies: []
14
14
  description: Contains core classes and interfaces for building event logger implementations.
15
15
  Also includes helper classes for incorporating assertions about event logging into