build-tool 0.5.7 → 0.6.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (133) hide show
  1. data/.gitignore +1 -0
  2. data/.rvmrc +1 -0
  3. data/.yardopts +1 -0
  4. data/Gemfile +5 -0
  5. data/Gemfile.lock +56 -0
  6. data/History.txt +64 -0
  7. data/README.txt +0 -7
  8. data/Rakefile +8 -56
  9. data/bin/build-tool +4 -1
  10. data/build-tool.gemspec +62 -0
  11. data/db/migrations/20110703074000_add_command_logs.rb +17 -0
  12. data/db/migrations/20110703075000_add_module_logs.rb +20 -0
  13. data/db/migrations/20110815170000_add_features.rb +17 -0
  14. data/db/migrations/20120103204700_add_modules.rb +17 -0
  15. data/db/migrations/20120106181200_add_settings.rb +18 -0
  16. data/lib/build-tool.rb +3 -4
  17. data/lib/build-tool/application.rb +127 -37
  18. data/lib/build-tool/build-system/autoconf.rb +2 -8
  19. data/lib/build-tool/build-system/base.rb +12 -4
  20. data/lib/build-tool/build-system/cmake.rb +2 -0
  21. data/lib/build-tool/build-system/custom.rb +2 -0
  22. data/lib/build-tool/build-system/kdel10n.rb +2 -0
  23. data/lib/build-tool/build-system/make.rb +2 -0
  24. data/lib/build-tool/build-system/none.rb +2 -0
  25. data/lib/build-tool/build-system/qmake.rb +2 -0
  26. data/lib/build-tool/build-system/qt.rb +4 -0
  27. data/lib/build-tool/cfg/lexer.rex +40 -8
  28. data/lib/build-tool/cfg/lexer_base.rb +3 -1
  29. data/lib/build-tool/cfg/node.rb +17 -1
  30. data/lib/build-tool/cfg/parser.y +92 -10
  31. data/lib/build-tool/cfg/visitor.rb +202 -78
  32. data/lib/build-tool/command_actions.rb +26 -10
  33. data/lib/build-tool/commands.rb +289 -197
  34. data/lib/build-tool/commands/build.rb +13 -9
  35. data/lib/build-tool/commands/configuration.rb +25 -0
  36. data/lib/build-tool/commands/configuration/edit.rb +42 -0
  37. data/lib/build-tool/commands/configuration/list.rb +48 -0
  38. data/lib/build-tool/commands/configure.rb +9 -5
  39. data/lib/build-tool/commands/ctags.rb +8 -3
  40. data/lib/build-tool/commands/environments.rb +2 -4
  41. data/lib/build-tool/commands/environments/list.rb +13 -10
  42. data/lib/build-tool/commands/environments/set.rb +5 -1
  43. data/lib/build-tool/commands/features.rb +24 -0
  44. data/lib/build-tool/commands/features/disable.rb +70 -0
  45. data/lib/build-tool/commands/features/enable.rb +66 -0
  46. data/lib/build-tool/commands/features/list.rb +92 -0
  47. data/lib/build-tool/commands/fetch.rb +9 -3
  48. data/lib/build-tool/commands/files.rb +9 -5
  49. data/lib/build-tool/commands/gc.rb +48 -15
  50. data/lib/build-tool/commands/history.rb +21 -16
  51. data/lib/build-tool/commands/info.rb +16 -13
  52. data/lib/build-tool/commands/install.rb +8 -4
  53. data/lib/build-tool/commands/modules.rb +2 -4
  54. data/lib/build-tool/commands/modules/cleanup.rb +52 -0
  55. data/lib/build-tool/commands/modules/disable.rb +95 -0
  56. data/lib/build-tool/commands/modules/enable.rb +52 -0
  57. data/lib/build-tool/commands/modules/info.rb +44 -35
  58. data/lib/build-tool/commands/modules/list.rb +67 -15
  59. data/lib/build-tool/commands/modules/shell.rb +8 -2
  60. data/lib/build-tool/commands/rebase.rb +15 -7
  61. data/lib/build-tool/commands/recipes.rb +2 -4
  62. data/lib/build-tool/commands/recipes/add.rb +16 -2
  63. data/lib/build-tool/commands/recipes/edit.rb +72 -0
  64. data/lib/build-tool/commands/recipes/incoming.rb +11 -7
  65. data/lib/build-tool/commands/recipes/info.rb +12 -8
  66. data/lib/build-tool/commands/recipes/install.rb +37 -42
  67. data/lib/build-tool/commands/recipes/list.rb +6 -2
  68. data/lib/build-tool/configuration.rb +88 -3
  69. data/lib/build-tool/environment.rb +2 -0
  70. data/lib/build-tool/errors.rb +5 -0
  71. data/lib/build-tool/history.rb +3 -181
  72. data/lib/build-tool/model/command_log.rb +93 -0
  73. data/lib/build-tool/model/feature.rb +80 -0
  74. data/lib/build-tool/{module.rb → model/module.rb} +110 -29
  75. data/lib/build-tool/model/module_log.rb +64 -0
  76. data/lib/build-tool/model/setting.rb +84 -0
  77. data/lib/build-tool/recipe.rb +40 -18
  78. data/lib/build-tool/repository.rb +39 -33
  79. data/lib/build-tool/server.rb +27 -3
  80. data/lib/build-tool/singleton.rb +2 -0
  81. data/lib/build-tool/sshkey.rb +2 -0
  82. data/lib/build-tool/state_helper.rb +64 -0
  83. data/lib/build-tool/vcs/archive.rb +3 -1
  84. data/lib/build-tool/vcs/base.rb +13 -0
  85. data/lib/build-tool/vcs/git-svn.rb +36 -14
  86. data/lib/build-tool/vcs/git.rb +180 -44
  87. data/lib/build-tool/vcs/mercurial.rb +25 -13
  88. data/lib/build-tool/vcs/svn.rb +20 -15
  89. data/lib/build-tool/version.rb +30 -0
  90. data/lib/mj/error.rb +2 -0
  91. data/lib/mj/logging.rb +2 -0
  92. data/lib/mj/mixins/inherited_attributes.rb +73 -0
  93. data/lib/mj/tools/editor.rb +34 -0
  94. data/lib/mj/tools/ssh.rb +2 -0
  95. data/lib/mj/tools/subprocess.rb +2 -1
  96. data/lib/mj/vcs/git.rb +14 -2
  97. data/lib/mj/visitor.rb +22 -0
  98. data/tasks/db.rake +36 -0
  99. data/tasks/racc.rake +14 -0
  100. data/tasks/rdoc.rake +8 -0
  101. data/tasks/rexical.rake +14 -0
  102. data/tasks/test.rake +21 -0
  103. data/test/integration/history_test.rb +88 -0
  104. data/test/integration/parser_configuration.rb +36 -0
  105. data/test/integration/parser_environment_parser.rb +156 -0
  106. data/test/integration/parser_feature_test.rb +75 -0
  107. data/test/integration/parser_git-svn_test.rb +92 -0
  108. data/test/integration/parser_git_test.rb +97 -0
  109. data/test/integration/parser_mercurial_test.rb +77 -0
  110. data/test/integration/parser_module_test.rb +103 -0
  111. data/test/integration/parser_svn_test.rb +92 -0
  112. data/test/integration/parser_test.rb +73 -0
  113. data/test/test_helper.rb +61 -0
  114. data/test/unit/configuration_test.rb +36 -0
  115. data/test/unit/git_configuration_test.rb +163 -0
  116. data/test/unit/git_svn_configuration_test.rb +240 -0
  117. data/test/unit/mercurial_configuration_test.rb +64 -0
  118. data/test/unit/model/command_log_test.rb +103 -0
  119. data/test/unit/model/feature_test.rb +29 -0
  120. data/test/unit/model/module_log_test.rb +70 -0
  121. data/test/unit/model/module_test.rb +32 -0
  122. data/test/unit/repository_test.rb +110 -0
  123. data/test/unit/server_test.rb +66 -0
  124. data/test/unit/svn_configuration_test.rb +90 -0
  125. metadata +134 -93
  126. data/Manifest.txt +0 -80
  127. data/db/migrations/001_command_histories.rb +0 -20
  128. data/db/migrations/002_module_events.rb +0 -24
  129. data/db/migrations/003_command_histories_add_logfile.rb +0 -19
  130. data/lib/build-tool/GUI.rb +0 -360
  131. data/lib/build-tool/commands/help.rb +0 -22
  132. data/lib/build-tool/commands/lsfeatures.rb +0 -76
  133. data/lib/build-tool/feature.rb +0 -47
@@ -1,3 +1,7 @@
1
+ # -*- coding: UTF-8 -*-
2
+
3
+ require 'mj/tools/ssh'
4
+
1
5
  require "build-tool/singleton"
2
6
  require 'build-tool/errors'
3
7
  require 'build-tool/command_actions'
@@ -76,6 +80,7 @@ class Base
76
80
  class UsageError < BuildTool::Error; end
77
81
 
78
82
  include HelpText
83
+ include ANSI::Code
79
84
 
80
85
  def <=> (other)
81
86
  return self.name <=> other.name
@@ -94,6 +99,7 @@ def initialize(parent = nil)
94
99
  @skip_command = false
95
100
  @parent = parent
96
101
  @cmd = nil
102
+ setup_options
97
103
  end
98
104
 
99
105
  def applicable?
@@ -107,37 +113,7 @@ def configuration
107
113
  def initialize_options
108
114
  end
109
115
 
110
- def complete_readline_1_8( string )
111
- # Readline in 1.8 does not provide all needed information. We have to hand made
112
- # it ourselves. We get the complete commandline here.
113
-
114
- # We want the complete commandline in line_buffer
115
- line_buffer = string
116
- # An array of completed arguments/options in args
117
- args = Shellwords.shellwords( line_buffer )
118
-
119
- # And the string to complete in string. If the last character is a space we
120
- # complete from that. if not we take the last arg
121
- if line_buffer.empty? or line_buffer[-1] == 32
122
- args << ""
123
- end
124
-
125
- do_complete_1_8( args )
126
- end
127
-
128
- def do_complete_1_8( args )
129
- # puts "do_complete_1_8( #{args.inspect} )"
130
- compl = complete_arguments( args )
131
- if compl.length >= 1
132
- return compl.collect do |res|
133
- args.dup[0..-2].push(res).join(" ")
134
- end
135
- else
136
- return []
137
- end
138
- end
139
-
140
- def complete_readline_1_9( string )
116
+ def complete_readline( string )
141
117
  # We have three sources of information (ruby 1.9 only)
142
118
  # argument:
143
119
  # See Readline::completer_word_break_characters . The part
@@ -148,7 +124,7 @@ def complete_readline_1_9( string )
148
124
  # The position of the cursor in commandline
149
125
  # Ruby 1.9 <start>
150
126
  # First check if we have to complete the first shellword (command)
151
- args = Shellwords.shellwords( string )
127
+ args = Shellwords.shellwords( Readline.line_buffer )
152
128
 
153
129
  # And the string to complete in string. If the last character is a space we
154
130
  # complete from that. if not we take the last arg
@@ -156,19 +132,7 @@ def complete_readline_1_9( string )
156
132
  args << ""
157
133
  end
158
134
 
159
- do_complete_1_9( args )
160
- end
161
-
162
- def do_complete_1_9( args )
163
- return complete_arguments( args )
164
- end
165
-
166
- def complete( string )
167
- if Readline.respond_to? "line_buffer"
168
- complete_readline_1_9( string )
169
- else
170
- complete_readline_1_8( string )
171
- end
135
+ do_complete( args )
172
136
  end
173
137
 
174
138
  def complete_arguments( args )
@@ -187,6 +151,11 @@ def complete_arguments( args )
187
151
  res.flatten.compact.sort
188
152
  end
189
153
 
154
+ def do_complete( args )
155
+ return complete_arguments( args )
156
+ do_complete( args )
157
+ end
158
+
190
159
  def each_option
191
160
  list = options.instance_variable_get( "@stack" )
192
161
  if block_given?
@@ -197,7 +166,11 @@ def each_option
197
166
  end
198
167
  end
199
168
  else
200
- list.collect { |l| l.list.collect { |sw| sw unless sw.is_a? String } }.flatten.compact
169
+ list.collect { |l|
170
+ l.list.collect { |sw|
171
+ sw unless not sw.is_a? OptionParser::Switch
172
+ }
173
+ }.flatten.compact
201
174
  end
202
175
  end
203
176
 
@@ -217,40 +190,49 @@ def summarize
217
190
  # Cleanup after vcs_access
218
191
  def cleanup_after_vcs_access
219
192
  if MJ::Tools::SSH::has_keys?
220
- logger.info ""
221
- logger.info "#### Cleaning up the ssh keys"
193
+ info( "" )
194
+ info( "#### Cleaning up the ssh keys" )
222
195
  MJ::Tools::SSH::keys.each do |file|
223
- logger.info " - Removing key #{file}"
196
+ info( " - Removing key #{file}" )
224
197
  end
225
198
  MJ::Tools::SSH::cleanup()
226
199
  end
227
200
  end
228
201
 
229
- def execute( args )
202
+ def setup_options
230
203
  @options = OptionParser.new
231
204
  @options.set_program_name( name )
232
- @options.separator long_description if long_description
233
-
234
- @parsing = true
205
+ if long_description
206
+ @options.separator ''
207
+ @options.separator long_description
208
+ end
235
209
  initialize_options
210
+ end
211
+
212
+ def execute( args )
213
+ # Reinitialize the option parser.
214
+ setup_options
236
215
  begin
237
216
  realargs = @options.parse( args )
238
217
  rescue OptionParser::ParseError => e
239
- logger.error( "#{e}" )
218
+ error( "#{name}: #{e}" )
240
219
  @skip_command = true
241
220
  end
242
- @parsing = false
243
221
 
244
222
  setup_command
245
223
 
246
224
  # Log the command into history
247
225
  state = BuildTool::History::CommandLog::FINISHED_SUCCESSFUL
248
226
  rc = -1 # -1 for @skip_command
249
- if log?
250
- @cmd = BuildTool::History::CommandLog.new( :command => "#{self.fullname} #{args.join( ' ')}", :logdir => log_directory )
251
- @cmd.started
252
- end
253
227
  if !@skip_command
228
+ # Initialize the command log if necessary
229
+ if log?
230
+ @cmd = BuildTool::History::CommandLog.new(
231
+ :command => "#{self.fullname} #{args.join( ' ')}",
232
+ :logdir => log_directory.to_s.encode( 'UTF-8' ) )
233
+ @cmd.started
234
+ end
235
+ # Now execute the command
254
236
  begin
255
237
  rc = do_execute( realargs )
256
238
  if rc != 0
@@ -258,8 +240,8 @@ def execute( args )
258
240
  end
259
241
  rescue BuildTool::Error => e
260
242
  state = BuildTool::History::CommandLog::FINISHED_WITH_ERRORS
261
- logger.error e.message
262
- logger.verbose e.backtrace.join("\n")
243
+ error( e.message )
244
+ verbose( e.backtrace.join("\n") )
263
245
  rc = -1
264
246
  rescue Interrupt => e
265
247
  state = BuildTool::History::CommandLog::CANCELED_BY_USER
@@ -303,7 +285,7 @@ def log?
303
285
 
304
286
  def show_help( args = [] )
305
287
  # Just ignore potential arguments
306
- say @options.help
288
+ info( options.help )
307
289
  skip_command
308
290
  return 0
309
291
  end
@@ -314,12 +296,42 @@ def skip_command
314
296
  @skip_command = true
315
297
  end
316
298
 
317
- def say( *args )
299
+ # Print out a normal message (if enabled)
300
+ def info( *args )
318
301
  logger.info( *args )
319
302
  end
320
303
 
304
+ # Print out a verbose message (if enabled)
305
+ def verbose( *args )
306
+ logger.verbose( *args )
307
+ end
308
+
309
+ # Print out a verbose message (if enabled)
310
+ def trace( *args )
311
+ logger.trace( *args )
312
+ end
313
+
314
+ # Print out a verbose message (if enabled)
315
+ def debug( *args )
316
+ logger.debug( *args )
317
+ end
318
+
319
+ def debug2( *args )
320
+ logger.debug2( *args )
321
+ end
322
+
323
+ # Print out a warning message (if enabled)
324
+ def warn( *args )
325
+ logger.warn( *args )
326
+ end
327
+
328
+ # Print out a error message (if enabled)
329
+ def error( *args )
330
+ logger.error( *args )
331
+ end
332
+
321
333
  def usage( error )
322
- logger.error error
334
+ error( error )
323
335
  show_help
324
336
  return -2
325
337
  end
@@ -348,12 +360,11 @@ def initialize( *args )
348
360
  end
349
361
 
350
362
  def initialize_options
363
+ options.separator ''
351
364
  options.separator "Common options"
352
365
 
353
366
  options.on( "-v", "--verbose", "Enable verbose output" ) do
354
- Logging.appenders['stdout'].level = [ Logging.appenders['stdout'].level-1, 0 ].max
355
- Logging.logger['MJ::Logging::LoggerAdapter'].level =
356
- [ Logging.logger['MJ::Logging::LoggerAdapter'].level - 1, 0 ].max
367
+ Logging.appenders['stdout'].level = [ Logging.appenders['stdout'].level - 1, 0 ].max()
357
368
  end
358
369
 
359
370
  options.on( nil, "--dry-run", "Enable dry run." ) do
@@ -365,10 +376,20 @@ def initialize_options
365
376
  end
366
377
  end
367
378
 
379
+ # Complete buildsets
380
+ def complete_buildsets( name )
381
+ if name == ':all'
382
+ return complete_modules( '*' )
383
+ end
384
+ end
385
+
368
386
  # Gathers all modules currently known.
369
387
  #
370
388
  # @param all Return template modules too.
371
389
  def complete_modules( name, include_templates = false )
390
+ if name.start_with? ':'
391
+ return complete_buildsets( name )
392
+ end
372
393
  res = []
373
394
  found = false
374
395
  should_be_unique = false
@@ -388,14 +409,15 @@ def complete_modules( name, include_templates = false )
388
409
  elsif mod.name == name
389
410
  found = true
390
411
  should_be_unique = true
412
+ take_module = true
413
+ elsif name == '*'
414
+ found = true
391
415
  # Now check if it is active.
392
416
  next if !( mod.active? || @all )
393
417
  take_module = true
394
418
  elsif mod.name.end_with?( "/#{name}" )
395
419
  found = true
396
420
  should_be_unique = true
397
- # Now check if it is active.
398
- next if !( mod.active? || @all )
399
421
  take_module = true
400
422
  end
401
423
 
@@ -422,7 +444,7 @@ def complete_modules( name, include_templates = false )
422
444
  end
423
445
 
424
446
  # Give a warning if all modules where
425
- logger.warn "All modules for #{name} are inactive! Will ignore it." if res.empty?
447
+ warn( "All modules for #{name} are inactive! Will ignore it." ) if res.empty?
426
448
  return res
427
449
  end
428
450
 
@@ -439,13 +461,13 @@ def while_logging_to( dir, fname, level, &block )
439
461
  got_exception = false
440
462
  # Only create a logfile if we do real work
441
463
  if log?
442
- dirname = log_directory.to_s
443
- dirname = "#{log_directory.to_s}/#{dir}" if dir
464
+ dirname = log_directory
465
+ dirname += dir if dir
444
466
  FileUtils.mkdir_p( dirname )
445
467
  Logging.logger['root'].add_appenders(
446
468
  Logging.appenders.file(
447
469
  fname,
448
- :filename => dirname + '/' + fname,
470
+ :filename => dirname + fname,
449
471
  :layout => Logging::Layouts::Pattern.new( :pattern => '%m\n' ),
450
472
  :level => level ))
451
473
  end
@@ -453,18 +475,18 @@ def while_logging_to( dir, fname, level, &block )
453
475
  begin
454
476
  yield
455
477
  rescue Interrupt => e
456
- logger.error "User Interrupt!"
478
+ error( "User Interrupt!" )
457
479
  rescue BuildTool::Error => e
458
- logger.error "#{e.message}"
480
+ error( "#{e.message}" )
459
481
  got_exception = true
460
482
  raise e
461
483
  rescue Exception => e
462
- logger.error "#{e.class}:#{e.message}"
484
+ error( "#{e.class}:#{e.message}" )
463
485
  got_exception = true
464
486
  raise e
465
487
  ensure
466
488
  Logging.logger['root'].remove_appenders( fname )
467
- logger.info("More information in #{dirname}/#{fname}") if got_exception
489
+ info( "More information in #{dirname}/#{fname}" ) if got_exception
468
490
  end
469
491
  end
470
492
 
@@ -527,7 +549,8 @@ def write( event )
527
549
  @pbar.clear() if @pbar
528
550
  @oldlogger.append(event)
529
551
  rescue Exception => e
530
- puts e
552
+ error( e )
553
+ verbose( e.backtrace.join("\n") )
531
554
  end
532
555
  end
533
556
  end
@@ -545,7 +568,7 @@ def initialize( *args )
545
568
  end
546
569
 
547
570
  def initialize_options
548
- options.on( "--resume-from [module]", "Skip all module before module." ) { |t|
571
+ options.on( "--resume-from MODULE", "Skip all module before module." ) { |t|
549
572
  begin
550
573
  @resume_from = complete_module( t )
551
574
  rescue UsageError => e
@@ -553,7 +576,7 @@ def initialize_options
553
576
  end
554
577
  raise UsageError, "Both --resume-from and --resume-after specified!" if @resume_after
555
578
  }
556
- options.on( "--resume-after [module]", "Skip all module before and including module." ) { |t|
579
+ options.on( "--resume-after MODULE", "Skip all module before and including module." ) { |t|
557
580
  begin
558
581
  @resume_after = complete_module( t )
559
582
  rescue UsageError => e
@@ -592,14 +615,27 @@ def do_execute( args )
592
615
  end
593
616
 
594
617
  # 2. Check if the modules are ready
595
- logger.info( '#### Checking for obstacles' )
618
+ info( '#### Checking for obstacles' )
596
619
  isready = true
597
620
  ModuleProgressbar.new( 'Modules', modules ) do |mod|
598
- isready &= is_module_ready?( mod )
621
+ begin
622
+ isready &= is_module_ready?( mod )
623
+ rescue Interrupt => e
624
+ info( "User Interrupt" )
625
+ return -1
626
+ rescue BuildTool::Error => e
627
+ error( e.message )
628
+ verbose( e.backtrace.join("\n") )
629
+ raise
630
+ rescue Exception => e
631
+ error( "#{e.class}:#{e.message}" )
632
+ verbose( e.backtrace.join("\n") )
633
+ raise
634
+ end
599
635
  end
600
636
 
601
637
  if !isready
602
- logger.error "There were some problems detected. Exiting."
638
+ error( "There were some problems detected. Exiting." )
603
639
  return -1
604
640
  end
605
641
 
@@ -608,13 +644,21 @@ def do_execute( args )
608
644
  begin
609
645
  isready &= prepare_module( mod )
610
646
  rescue Interrupt => e
611
- logger.info( "User Interrupt" )
647
+ info( "User Interrupt" )
612
648
  return -1
649
+ rescue BuildTool::Error => e
650
+ error( e.message )
651
+ verbose( e.backtrace.join("\n") )
652
+ raise
653
+ rescue Exception => e
654
+ error( "#{e.class}:#{e.message}" )
655
+ verbose( e.backtrace.join("\n") )
656
+ raise
613
657
  end
614
658
  end
615
659
 
616
660
  if !isready
617
- logger.error "Unexpected problems encountered. Exiting."
661
+ error( "Unexpected problems encountered. Exiting." )
618
662
  return -1
619
663
  end
620
664
 
@@ -630,25 +674,25 @@ def do_execute( args )
630
674
 
631
675
  begin
632
676
 
633
- logger.info ""
634
- logger.info "#### Module #{mod.name} (#{index+1}/#{modules.size})"
677
+ info( "" )
678
+ info( "#### Module #{mod.name} (#{index+1}/#{modules.size})" )
635
679
  do_execute_module( mod )
636
680
  rescue Interrupt => e
637
681
  raise e
638
682
  rescue BuildTool::Error => e
639
- logger.error e.message
640
- logger.verbose e.backtrace.join("\n")
683
+ error( e.message )
684
+ verbose( e.backtrace.join("\n") )
641
685
  @failed_modules << mod.name
642
686
  rc = -1
643
687
  break if @stop_on_error
644
688
  rescue Exception => e
645
- logger.error "#{e.class}:#{e.message}"
646
- logger.verbose e.backtrace.join("\n")
689
+ error( "#{e.class}:#{e.message}" )
690
+ verbose( e.backtrace.join("\n") )
647
691
  @failed_modules << mod.name
648
692
  rc = -1
649
693
  break if @stop_on_error
650
694
  ensure
651
- logger.info "#### Module #{mod.name} finished"
695
+ info( "#### Module #{mod.name} finished" )
652
696
  end
653
697
  end
654
698
 
@@ -661,12 +705,12 @@ def do_execute( args )
661
705
  end
662
706
 
663
707
  def summarize
664
- logger.info ""
708
+ info( "" )
665
709
  if !@failed_modules.empty?
666
- logger.info "#### Finished with errors"
667
- logger.info "Failed modules:\n\t#{ @failed_modules.join( "\n\t" ) }"
710
+ info( "#### Finished with errors" )
711
+ info( "Failed modules:\n\t#{ @failed_modules.join( "\n\t" ) }" )
668
712
  else
669
- logger.info "#### Finished without errors"
713
+ info( "#### Finished without errors" )
670
714
  end
671
715
  end
672
716
 
@@ -716,8 +760,8 @@ def make( mod, *args )
716
760
  # Call the #rebase method of the module.
717
761
  #
718
762
  # @param [Object] mod The module to use
719
- def rebase( mod )
720
- ModuleActions::Rebase.new( self, mod ).do
763
+ def rebase( mod, verbose = false )
764
+ ModuleActions::Rebase.new( self, mod, verbose ).do
721
765
  end
722
766
 
723
767
  # Call the #reconfigure method of the module.
@@ -727,11 +771,18 @@ def reconfigure( mod )
727
771
  ModuleActions::Reconfigure.new( self, mod ).do
728
772
  end
729
773
 
730
- # Call the #clear_build_directory method of the module.
774
+ # Call the #remove_build_directory method of the module.
775
+ #
776
+ # @param [Object] mod The module to use
777
+ def remove_build_directory( mod, force = false )
778
+ ModuleActions::RemoveBuildDirectory.new( self, mod, force ).do
779
+ end
780
+
781
+ # Call the #remove_source_directory method of the module.
731
782
  #
732
783
  # @param [Object] mod The module to use
733
- def remove_build_directory( mod )
734
- ModuleActions::RemoveBuildDirectory.new( self, mod ).do
784
+ def remove_source_directory( mod, force = false )
785
+ ModuleActions::RemoveSourceDirectory.new( self, mod, force ).do
735
786
  end
736
787
 
737
788
  end
@@ -747,8 +798,21 @@ def initialize( *args )
747
798
  @commands = []
748
799
  end
749
800
 
801
+ def initialize_options()
802
+ options.banner = "Usage: #{name} [OPTIONS]... COMMAND [COMMAND OPTIONS]..."
803
+
804
+ options.on( "-h", "--help", "Show this help text." ) do
805
+ show_help
806
+ end
807
+
808
+ options.separator( '' )
809
+ options.separator( "Use '#{name} help' to see a list of commands" )
810
+
811
+ super()
812
+ end
813
+
750
814
  def add_command( cmd )
751
- logger.trace "#{name}: Adding command #{cmd.name}"
815
+ trace( "#{name}: Adding command #{cmd.name}" )
752
816
  @commands << cmd
753
817
  end
754
818
 
@@ -765,77 +829,63 @@ def get_command( name )
765
829
  end
766
830
 
767
831
  def execute( args )
768
- # There has to be a subcommand
769
- if args.length == 0
770
- return show_help
832
+ debug2( '%s: %s' % [ name, args ] )
833
+
834
+ # Reinitialize the option parser.
835
+ setup_options
836
+
837
+ # Parse our options. Store the rest for later.
838
+ begin
839
+ args = @options.order( args )
840
+ rescue OptionParser::ParseError => e
841
+ error( "#{name}: #{e}" )
842
+ return -1
771
843
  end
772
844
 
773
- cmd = get_command( args[0] )
774
- if cmd.nil?
775
- if self.name
776
- raise UsageError, "Unknown command #{args[0]} for #{self.name}"
777
- else
778
- raise UsageError, "Unknown command #{args[0]}"
845
+ setup_command
846
+
847
+ begin
848
+
849
+ # There has to be a subcommand
850
+ if args.length == 0
851
+ return default_command()
779
852
  end
780
- end
781
- cmd.execute( args[1..-1] )
782
- end
783
853
 
784
- def do_complete_1_8( args )
785
- # puts "#{self.name}.do_complete_1_8( #{args.inspect}"
786
- if args.length <= 1
787
- # There is only one or no argument. We try to complete to a
788
- # command.
789
- if subcmd = get_command( args[0] )
790
- # We have a exact match. If we had to complete to get to
791
- # the commands return here. If not forward to the command
792
- if args[0] != subcmd.name
793
- return [ subcmd.name ]
854
+ # Always accept help as a command
855
+ return help_commands() if args[0] == 'help'
856
+
857
+ # Now follow up with real ones.
858
+ cmd = get_command( args[0] )
859
+ if cmd.nil?
860
+ if self.name
861
+ raise UsageError, "Unknown command #{args[0]} for #{self.name}"
794
862
  else
795
- return subcmd.do_complete_1_8( [""] ).collect do |res|
796
- [ subcmd.name ].push(res).join(" ")
797
- end
798
- end
799
- else
800
- # We have a no exact match. Complete the available
801
- # commands
802
- return complete_command( args[0] )
803
- end
804
- else
805
- # At least two arguments are present
806
- if subcmd = get_command( args[0] )
807
- # We have a exact match. Forward to that command.
808
- return subcmd.do_complete_1_8( args[1..-1] ).collect do |res|
809
- [ subcmd.name ].push(res).join(" ")
863
+ raise UsageError, "Unknown command #{args[0]}"
810
864
  end
811
- else
812
- # No exact match. Since there is at least on argument
813
- # behind the current position just keep the user input
814
- # intact.
815
- return []
816
865
  end
866
+
867
+ cmd.execute( args[1..-1] )
868
+ ensure
869
+
870
+ teardown_command
817
871
  end
818
872
  end
819
873
 
820
- def do_complete_1_9( args )
821
- # puts "#{self.name}.do_complete_1_9( #{args.inspect} )"
822
- if args.length <= 1
823
- if subcmd = get_command( args[0] )
824
- return subcmd.do_complete_1_9( [""] )
825
- else
826
- return complete_command( args[0] )
827
- end
874
+ def do_complete( args )
875
+ cur = args[0]
876
+ # Check if we have a match for one command
877
+ if subcmd = get_command( cur )
878
+ # Check if the commands is complete. If not complete it.
879
+ return [ subcmd.name() ] if cur != subcmd.name()
880
+ # It is complete. forward.
881
+ return subcmd.do_complete( args[1..-1] )
828
882
  else
829
- if subcmd = get_command( args[0] )
830
- return subcmd.do_complete_1_9( args[1..-1] )
831
- else
832
- return args
833
- end
883
+ # No match. Give back possible matches.
884
+ return complete_command( cur )
834
885
  end
835
886
  end
836
887
 
837
888
  def complete_command( cmdname )
838
- # puts "#{self.name}.complete_command( #{cmdname.inspect} )"
839
889
  cmds = @commands.collect { |com|
840
890
  com.name if com.name.start_with? cmdname
841
891
  }.compact
@@ -850,27 +900,8 @@ def complete_arguments( args, string )
850
900
  end
851
901
  end
852
902
 
853
- def show_help( args = [] )
854
- if args.length == 0
855
- @commands.sort.each do |cmd|
856
- say "%-20s: %s" % [ cmd.name, cmd.description ]
857
- end
858
- else
859
- if cmd = get_command( args[0] )
860
- cmd.show_help( args[1..-1] )
861
- else
862
- if self.name
863
- raise UsageError, "Unknown command #{args[0]} for #{self.name}"
864
- else
865
- raise UsageError, "Unknown command #{args[0]}"
866
- end
867
- end
868
- end
869
- return 0
870
- end
871
-
872
903
  def load_commands( path, parentmod, submod = nil )
873
- logger.debug "load_commands( #{path} #{parentmod.inspect} #{submod.inspect}"
904
+ debug( "load_commands( #{path} #{parentmod.inspect} #{submod.inspect}" )
874
905
  # Load all available ruby files in path
875
906
  Dir[ "#{path}/*.rb" ].each do |mod|
876
907
  load "#{mod}"
@@ -913,6 +944,19 @@ def load_commands( path, parentmod, submod = nil )
913
944
 
914
945
  end
915
946
 
947
+ def show_help()
948
+ super()
949
+ end
950
+
951
+ def help_commands( args = [] )
952
+ @commands.sort.each do |cmd|
953
+ info( "%-20s: %s" % [ cmd.name, cmd.description ] )
954
+ end
955
+ return 0
956
+ end
957
+
958
+ alias :default_command :help_commands
959
+
916
960
  end # class SubCommands
917
961
 
918
962
  #
@@ -920,23 +964,73 @@ def load_commands( path, parentmod, submod = nil )
920
964
  #
921
965
  class Shell < SubCommands
922
966
 
923
- name "shell"
967
+ def name
968
+ return Pathname.new($0).basename.to_s
969
+ end
924
970
 
925
- def execute( args )
926
- if args.length == 0
927
- return cli
971
+ def initialize_options
972
+ options.banner = "Usage: #{name} [OPTIONS]... COMMAND [COMMAND OPTIONS]..."
973
+
974
+ options.separator ''
975
+ options.separator "Options"
976
+
977
+ options.on( "-v", "--verbose", "Enable verbose output" ) do
978
+ Logging.appenders['stdout'].level = [ Logging.appenders['stdout'].level - 1, 0 ].max()
928
979
  end
929
- super
980
+
981
+ options.on( nil, "--dry-run", "Enable dry run." ) do
982
+ $noop = true
983
+ end
984
+
985
+ options.on( "-V", "--version", "Print version information." ) do
986
+ show_version
987
+ end
988
+
989
+ options.on( "--ionice", "Set io io niceness to idle (3)." ) { |n|
990
+
991
+ pid = Process.pid()
992
+ system( "ionice -p #{pid} -c 3" )
993
+ cur = `ionice -p #{pid}`
994
+ info( 'Process priority (io niceness): %s' % cur )
995
+ }
996
+
997
+ options.on( "--nice N", "Set niceness to N." ) { |n|
998
+ if not /^[0-9]+$/.match( n )
999
+ raise OptionParser::ParseError.new( 'value "%s" is not a number' % n )
1000
+ end
1001
+
1002
+ # Set the priority
1003
+ Process.setpriority( Process::PRIO_PROCESS, 0, n.to_i() )
1004
+
1005
+ # Check if it worked.
1006
+ cur = Process.getpriority( Process::PRIO_PROCESS, 0 )
1007
+ if n.to_i() != cur
1008
+ warn( 'Process priority (niceness): %d (%d was given)' % [ cur, n ] )
1009
+ else
1010
+ info( 'Process priority (niceness): %d' % [ cur ] )
1011
+ end
1012
+ }
1013
+
1014
+ options.on( "--debug-db", "Debug the database." ) do
1015
+ Logging.logger['ActiveRecord'].level = :debug
1016
+ end
1017
+
1018
+ super()
1019
+ end
1020
+
1021
+ def setup_command
1022
+ # And the commands require all that database related stuff.
1023
+ load_commands( Application::instance.application_root.join( "lib/build-tool/commands" ), BuildTool::Commands )
1024
+ end
1025
+
1026
+ def show_version
1027
+ @skip_command = true
1028
+ info( "#{name()}: Version #{BuildTool::VERSION}" )
930
1029
  end
931
1030
 
932
1031
  def cli
933
1032
  require 'readline'
934
-
935
- Readline.completion_proc = method(:complete)
936
- if !Readline.respond_to? "line_buffer"
937
- # 1.8 :(
938
- Readline.completer_word_break_characters = "\x00"
939
- end
1033
+ Readline.completion_proc = method(:complete_readline)
940
1034
 
941
1035
  while true
942
1036
 
@@ -958,13 +1052,13 @@ def cli
958
1052
  execute Shellwords.shellwords( line )
959
1053
 
960
1054
  rescue BuildTool::Error => e
961
- logger.error e.message
962
- logger.verbose e.backtrace.join("\n")
1055
+ error( e.message )
1056
+ verbose( e.backtrace.join("\n") )
963
1057
  rescue StandardError => e
964
- logger.error e.message
965
- logger.error e.backtrace.join("\n")
1058
+ error( e.message )
1059
+ error( e.backtrace.join("\n") )
966
1060
  rescue Interrupt => e
967
- say "Use CTRL-D for exit!"
1061
+ info( "Use CTRL-D for exit!" )
968
1062
  end
969
1063
 
970
1064
  end
@@ -972,9 +1066,7 @@ def cli
972
1066
  return 0
973
1067
  end
974
1068
 
975
- def fullname
976
- nil
977
- end
1069
+ alias :default_command :cli
978
1070
 
979
1071
  end # class Shell
980
1072