build-tool 0.1.4 → 0.2

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.
Files changed (90) hide show
  1. data.tar.gz.sig +2 -3
  2. data/History.txt +29 -0
  3. data/Manifest.txt +39 -10
  4. data/README.txt +5 -8
  5. data/Rakefile +14 -6
  6. data/bin/build-tool +3 -35
  7. data/db/migrations/001_command_histories.rb +20 -0
  8. data/db/migrations/002_module_events.rb +24 -0
  9. data/db/migrations/003_command_histories_add_logfile.rb +19 -0
  10. data/lib/build-tool.rb +1 -1
  11. data/lib/build-tool/application.rb +103 -30
  12. data/lib/build-tool/build-system/autoconf.rb +69 -6
  13. data/lib/build-tool/build-system/base.rb +2 -25
  14. data/lib/build-tool/build-system/custom.rb +6 -19
  15. data/lib/build-tool/build-system/kdel10n.rb +39 -0
  16. data/lib/build-tool/build-system/none.rb +82 -0
  17. data/lib/build-tool/cfg/lexer.rb +133 -7
  18. data/lib/build-tool/cfg/lexer.rex +58 -6
  19. data/lib/build-tool/cfg/node.rb +13 -1
  20. data/lib/build-tool/cfg/parser.rb +519 -333
  21. data/lib/build-tool/cfg/parser.y +74 -11
  22. data/lib/build-tool/cfg/visitor.rb +182 -20
  23. data/lib/build-tool/command_actions.rb +202 -0
  24. data/lib/build-tool/commands.rb +193 -49
  25. data/lib/build-tool/commands/build.rb +13 -8
  26. data/lib/build-tool/commands/configure.rb +8 -3
  27. data/lib/build-tool/commands/environments.rb +4 -8
  28. data/lib/build-tool/commands/environments/list.rb +8 -0
  29. data/lib/build-tool/commands/fetch.rb +7 -2
  30. data/lib/build-tool/commands/gc.rb +53 -0
  31. data/lib/build-tool/commands/history.rb +111 -0
  32. data/lib/build-tool/commands/install.rb +6 -1
  33. data/lib/build-tool/commands/lsfeatures.rb +73 -0
  34. data/lib/build-tool/commands/modules.rb +3 -7
  35. data/lib/build-tool/commands/modules/info.rb +15 -6
  36. data/lib/build-tool/commands/modules/list.rb +10 -5
  37. data/lib/build-tool/commands/rebase.rb +6 -1
  38. data/lib/build-tool/commands/recipes.rb +3 -7
  39. data/lib/build-tool/configuration.rb +24 -1
  40. data/lib/build-tool/environment.rb +17 -3
  41. data/lib/build-tool/feature.rb +47 -0
  42. data/lib/build-tool/history.rb +173 -0
  43. data/lib/build-tool/module.rb +49 -90
  44. data/lib/build-tool/recipe.rb +5 -0
  45. data/lib/build-tool/vcs/archive.rb +140 -0
  46. data/lib/build-tool/vcs/base.rb +5 -5
  47. data/lib/build-tool/vcs/git-svn.rb +4 -0
  48. data/lib/build-tool/vcs/git.rb +4 -0
  49. data/lib/mj/logging.rb +11 -0
  50. data/recipes/{kdeqt4.6 → kde}/custom/qt/qtscriptgenerator/compile.sh +0 -0
  51. data/recipes/{kdeqt4.6 → kde}/custom/qt/qtscriptgenerator/configure.sh +0 -0
  52. data/recipes/{kdeqt4.6 → kde}/custom/qt/qtscriptgenerator/install.sh +0 -0
  53. data/recipes/kde/custom/scripting/pyqt4/compile.sh +10 -0
  54. data/recipes/kde/custom/scripting/pyqt4/configure.sh +14 -0
  55. data/recipes/kde/custom/scripting/pyqt4/install.sh +10 -0
  56. data/recipes/kde/custom/scripting/sip/compile.sh +10 -0
  57. data/recipes/kde/custom/scripting/sip/configure.sh +13 -0
  58. data/recipes/kde/custom/scripting/sip/install.sh +10 -0
  59. data/recipes/kde/files/xsession +8 -4
  60. data/recipes/kde/kde-bindings.recipe +22 -0
  61. data/recipes/kde/kde-core.recipe +104 -0
  62. data/recipes/kde/kde-devel.recipe +38 -0
  63. data/recipes/kde/kde-finance.recipe +17 -0
  64. data/recipes/kde/kde-graphics.recipe +27 -0
  65. data/recipes/kde/kde-kdevelop.recipe +116 -0
  66. data/recipes/kde/kde-l10n.recipe +14 -0
  67. data/recipes/kde/kde-multimedia.recipe +31 -0
  68. data/recipes/kde/kde-network.recipe +55 -0
  69. data/recipes/kde/kde-office.recipe +28 -0
  70. data/recipes/kde/kde-plasma.recipe +117 -0
  71. data/recipes/{kdeqt4.6/recipe → kde/kde-qt.recipe} +25 -57
  72. data/recipes/kde/kde-scripting.recipe +63 -0
  73. data/recipes/kde/kde-support.recipe +73 -0
  74. data/recipes/kde/kde-utils.recipe +22 -0
  75. data/recipes/kde/kde-webdev.recipe +41 -0
  76. data/recipes/kde/recipe +92 -532
  77. data/recipes/kde/recipe-local +58 -2
  78. data/recipes/kde/settings.yaml +17 -0
  79. data/recipes/kde43/recipe-local +58 -2
  80. data/test/test_configuration_parser.rb +76 -21
  81. data/test/test_feature.rb +34 -0
  82. data/test/test_history.rb +149 -0
  83. metadata +185 -30
  84. metadata.gz.sig +0 -0
  85. data/lib/build-tool/pluginbase.rb +0 -43
  86. data/recipes/kdeqt4.6/info.yaml +0 -7
  87. data/recipes/kdeqt4.6/recipe-local +0 -30
  88. data/recipes/kdeqt4.6/settings.yaml +0 -27
  89. data/tasks/rdoc.rake +0 -34
  90. data/test.rb +0 -28
@@ -0,0 +1,202 @@
1
+ require 'ftools'
2
+
3
+ module BuildTool
4
+
5
+ module ModuleActions
6
+
7
+ class Base
8
+
9
+ def initialize( command, prio, type, mod )
10
+ @command = command
11
+ @logdir = command.log_directory.join( mod.name )
12
+ @type = type
13
+ @prio = prio
14
+ @filename = "#{prio.to_s}_#{type.to_s}"
15
+ @logfile = @logdir.join( @filename )
16
+ @module = mod
17
+ end
18
+
19
+ def do
20
+ # Make sure the directory for this module exists
21
+ FileUtils.mkdir_p( @logdir ) if ! $noop
22
+
23
+ # Open the logfile and then execute the command
24
+ while_logging do
25
+ execute
26
+ end
27
+ end
28
+
29
+ #########
30
+ protected
31
+ #########
32
+
33
+ def while_logging( level = :trace, &block )
34
+ # Only create a logfile if we do real work
35
+ if !$noop
36
+ Logging.logger['root'].add_appenders(
37
+ Logging.appenders.file(
38
+ @filename,
39
+ :filename => @logfile,
40
+ :layout => Logging::Layouts::Pattern.new( :pattern => '%m\n' ),
41
+ :level => level ))
42
+ end
43
+
44
+ begin
45
+ # If there is an associated command_history entry, add a module_event entry
46
+ logentry = nil
47
+ state = History::ModuleLog::FINISHED_SUCCESSFUL
48
+ if @command.cmd
49
+ logentry = History::ModuleLog.new(
50
+ :module => @module.name,
51
+ :event => @type,
52
+ :logfile => @logfile)
53
+ @command.cmd.add_module_log(logentry)
54
+ logentry.started
55
+ end
56
+ logger.debug "Opening logfile #{@logfile}"
57
+ yield
58
+ rescue Interrupt => e
59
+ state = History::ModuleLog::CANCELED_BY_USER
60
+ logger.error "User Interrupt!"
61
+ raise e
62
+ rescue Exception => e
63
+ state = History::ModuleLog::FINISHED_WITH_ERRORS
64
+ logger.error "#{e.class}:#{e.message}"
65
+ got_exception = true
66
+ raise e
67
+ ensure
68
+ if logentry
69
+ logentry.finished( state )
70
+ end
71
+ Logging.logger['root'].remove_appenders( @filename )
72
+ logger.debug "Closing logfile #{@logfile}"
73
+ logger.info("More information in #{@logfile}") if got_exception
74
+ end
75
+ end
76
+
77
+ end
78
+
79
+ class Clean < Base
80
+
81
+ def initialize( command, mod, remove_build_directory )
82
+ super( command, 10, :clean, mod )
83
+ @remove_build_directory = remove_build_directory
84
+ end
85
+
86
+ def execute()
87
+ logger.info "Cleaning"
88
+ @module.clean( @remove_build_directory )
89
+ end
90
+
91
+ end
92
+
93
+ class Clone < Base
94
+
95
+ def initialize( command, mod )
96
+ super( command, 20, :fetch, mod )
97
+ end
98
+
99
+ def execute()
100
+ logger.info "Fetching"
101
+ @module.clone
102
+ end
103
+
104
+ end
105
+
106
+ class Fetch < Base
107
+
108
+ def initialize( command, mod )
109
+ super( command, 20, :fetch, mod )
110
+ if !mod.vcs_required.fetching_supported?
111
+ logger.info "Fetching/Rebase not supported by vcs #{mod.vcs.name}. Doing it in one step."
112
+ end
113
+ end
114
+
115
+ def execute()
116
+ logger.info "Fetching remote changes."
117
+ @module.fetch
118
+ end
119
+
120
+ end
121
+
122
+ class Rebase < Base
123
+
124
+ def initialize( command, mod )
125
+ super( command, 20, :rebase, mod )
126
+ if !mod.vcs_required.fetching_supported?
127
+ logger.info "Fetching not supported by vcs #{mod.vcs.name}. Doing nothing."
128
+ return
129
+ end
130
+ end
131
+
132
+ def execute()
133
+ logger.info "Rebasing"
134
+ @module.rebase
135
+ end
136
+
137
+ end
138
+
139
+ class Configure < Base
140
+
141
+ def initialize( command, mod )
142
+ super( command, 40, :configure, mod )
143
+ end
144
+
145
+ def execute()
146
+ logger.info "Configuring"
147
+ if !$noop and !@module.vcs_required.checkedout?
148
+ raise ConfigurationError, "Module is not checked out. Enable updating."
149
+ end
150
+ @module.configure
151
+ end
152
+
153
+ end
154
+
155
+ class Reconfigure < Base
156
+
157
+ def initialize( command, mod )
158
+ super( command, 40, :reconfigure, mod )
159
+ end
160
+
161
+ def execute()
162
+ logger.info "Reconfiguring"
163
+ if !$noop and !@module.vcs_required.checkedout?
164
+ raise ConfigurationError, "Module is not checked out. Enable updating."
165
+ end
166
+ @module.build_system_required.reconfigure
167
+ end
168
+
169
+ end
170
+
171
+ class Make < Base
172
+
173
+ def initialize( command, mod, target = nil )
174
+ super( command, 50, :compile, mod )
175
+ @target = target
176
+ end
177
+
178
+ def execute()
179
+ logger.info "Building"
180
+ @module.build_system_required.make( @target )
181
+ end
182
+
183
+ end
184
+
185
+ class Install < Base
186
+
187
+ def initialize( command, mod, fast = false )
188
+ super( command, 60, :install, mod )
189
+ @fast = fast
190
+ end
191
+
192
+ def execute()
193
+ logger.info "Installing"
194
+ @module.build_system_required.install( @fast )
195
+ end
196
+
197
+ end
198
+
199
+ end # module ModuleAction
200
+
201
+ end # module BuildTool
202
+
@@ -1,5 +1,7 @@
1
1
  require "build-tool/singleton"
2
2
  require 'build-tool/errors'
3
+ require 'build-tool/command_actions'
4
+ require 'build-tool/history'
3
5
  require 'shellwords'
4
6
  require 'optparse'
5
7
  require 'delegate'
@@ -70,15 +72,26 @@ module BuildTool; module Commands;
70
72
 
71
73
  include HelpText
72
74
 
75
+ def <=> (other)
76
+ return self.name <=> other.name
77
+ end
78
+
79
+ # The OptionParser instance associated with this command
73
80
  attr_reader :options
81
+
82
+ # The parent command if this is a sub command
74
83
  attr_reader :parent
75
84
 
85
+ # The commands entry in the history db or nil
86
+ attr_accessor :cmd
87
+
76
88
  def initialize(parent = nil)
77
89
  @options = OptionParser.new
78
90
  @options.set_program_name( name )
79
91
  initialize_options
80
92
  @skip_command = false
81
93
  @parent = parent
94
+ @cmd = nil
82
95
  end
83
96
 
84
97
  def applicable?
@@ -204,17 +217,57 @@ module BuildTool; module Commands;
204
217
  end
205
218
  @parsing = false
206
219
 
220
+ # Log the command into history
221
+ state = BuildTool::History::CommandLog::FINISHED_SUCCESSFUL
222
+ rc = -1 # -1 for @skip_command
223
+ if log?
224
+ @cmd = BuildTool::History::CommandLog.new( :command => "#{self.fullname} #{args.join( ' ')}", :logdir => log_directory )
225
+ @cmd.started
226
+ end
207
227
  if !@skip_command
208
228
  begin
209
- return do_execute( realargs )
229
+ rc = do_execute( realargs )
230
+ if rc != 0
231
+ state = BuildTool::History::CommandLog::FINISHED_WITH_ERRORS
232
+ end
210
233
  rescue BuildTool::Error => e
234
+ state = BuildTool::History::CommandLog::FINISHED_WITH_ERRORS
211
235
  logger.error e.message
212
236
  logger.verbose e.backtrace.join("\n")
237
+ rc = -1
238
+ rescue Interrupt => e
239
+ state = BuildTool::History::CommandLog::CANCELED_BY_USER
240
+ raise e
241
+ ensure
242
+ if @cmd
243
+ @cmd.finished( state )
244
+ @cmd = nil
245
+ end
213
246
  end
214
247
  end
215
248
 
216
249
  # Either we skipped the command or we catched an exception
217
- return -1;
250
+ return rc;
251
+ end
252
+
253
+ # Return the commands full name.
254
+ #
255
+ # The full name includes the parents name (if any).
256
+ #
257
+ # @return [String] The commands full name
258
+ #
259
+ def fullname
260
+ if parent.fullname
261
+ return parent.fullname + " " + name
262
+ else
263
+ return name
264
+ end
265
+ end
266
+
267
+ # Should this command be logged?
268
+ #
269
+ def log?
270
+ false
218
271
  end
219
272
 
220
273
  def show_help( args = [] )
@@ -297,15 +350,18 @@ module BuildTool; module Commands;
297
350
 
298
351
  def while_logging_to( dir, fname, level, &block )
299
352
  got_exception = false
300
- dirname = @log_directory
301
- dirname = "#{@log_directory}/#{dir}" if dir
302
- FileUtils.mkdir_p( dirname )
303
- Logging.logger['root'].add_appenders(
304
- Logging.appenders.file(
305
- fname,
306
- :filename => dirname + '/' + fname,
307
- :layout => Logging::Layouts::Pattern.new( :pattern => '%m\n' ),
308
- :level => level ))
353
+ # Only create a logfile if we do real work
354
+ if log?
355
+ dirname = log_directory.to_s
356
+ dirname = "#{log_directory.to_s}/#{dir}" if dir
357
+ FileUtils.mkdir_p( dirname )
358
+ Logging.logger['root'].add_appenders(
359
+ Logging.appenders.file(
360
+ fname,
361
+ :filename => dirname + '/' + fname,
362
+ :layout => Logging::Layouts::Pattern.new( :pattern => '%m\n' ),
363
+ :level => level ))
364
+ end
309
365
 
310
366
  begin
311
367
  yield
@@ -321,29 +377,45 @@ module BuildTool; module Commands;
321
377
  end
322
378
  end
323
379
 
324
- def initialize_log_directory
380
+ # On demand initialization
381
+ def log_directory
382
+ return @log_directory if @log_directory
383
+
384
+ # Get the root logfile directory
325
385
  logdir = configuration.log_directory
326
386
 
327
- # Ensure the base log directory exists
387
+ # Try to find the next log directory for today.
388
+ i = -1
389
+ begin
390
+ @log_directory = logdir.join( "#{Date.today.to_s}-%02d" % i+=1 )
391
+ end until !@log_directory.exist?
392
+
393
+ # If noop is active we are finished
394
+ return @log_directory if $noop
395
+
396
+ # Ensure the base log directory exists.
328
397
  if !File.exist? "#{logdir}"
329
398
  FileUtils.mkdir_p "#{logdir}"
330
399
  end
331
400
 
332
- i = -1
333
-
334
- begin
335
- @log_directory = "#{logdir}/#{Date.today.to_s}-%02d" % i+=1
336
- end until !File.exist?( @log_directory )
337
-
338
- FileUtils.mkdir_p( @log_directory )
401
+ # Create the latest symbolic link
402
+ FileUtils.mkdir_p( @log_directory.to_s )
339
403
  FileUtils.rm_f( "#{logdir}/latest" )
340
- FileUtils.ln_sf( @log_directory, "#{logdir}/latest" )
404
+ FileUtils.ln_sf( @log_directory.to_s, "#{logdir}/latest" )
405
+
406
+ @log_directory
341
407
  end
342
408
 
409
+
343
410
  end # class Standard
344
411
 
345
412
  class ModuleBasedCommand < Standard
346
413
 
414
+ def initialize( *args )
415
+ @all = false
416
+ super( *args )
417
+ end
418
+
347
419
  def is_module_ready?( mod )
348
420
  true
349
421
  end
@@ -374,15 +446,14 @@ module BuildTool; module Commands;
374
446
  return -1
375
447
  end
376
448
 
377
- # 3. Let's go
378
- initialize_log_directory
379
-
380
449
  rc = 0 # Our return code.
381
450
 
382
451
  while_logging_to nil, 'build-status', :info do
383
452
 
384
453
  modules.each do |mod|
385
454
 
455
+ next if !( mod.active? || @all )
456
+
386
457
  begin
387
458
  logger.info ""
388
459
  logger.info "#### Module #{mod.name}"
@@ -407,6 +478,62 @@ module BuildTool; module Commands;
407
478
  return rc;
408
479
  end
409
480
 
481
+ # Call the #clean method of the module.
482
+ #
483
+ # @param [Object] mod The module to use
484
+ def clean( mod, *args )
485
+ ModuleActions::Clean.new( self, mod, *args ).do
486
+ end
487
+
488
+ # Call the #clone method of the module.
489
+ #
490
+ # @param [Object] mod The module to use
491
+ def clone( mod )
492
+ ModuleActions::Clone.new( self, mod ).do
493
+ end
494
+
495
+ # Call the #configure method of the module.
496
+ #
497
+ # @param [Object] mod The module to use
498
+ def configure( mod )
499
+ ModuleActions::Configure.new( self, mod ).do
500
+ end
501
+
502
+ # Call the #fetch method of the module.
503
+ #
504
+ # @param [Object] mod The module to use
505
+ def fetch( mod )
506
+ ModuleActions::Fetch.new( self, mod ).do
507
+ end
508
+
509
+ # Call the #install method of the module.
510
+ #
511
+ # @param [Object] mod The module to use
512
+ def install( mod, *args )
513
+ ModuleActions::Install.new( self, mod, *args ).do
514
+ end
515
+
516
+ # Call the #make method of the module.
517
+ #
518
+ # @param [Object] mod The module to use
519
+ def make( mod, *args )
520
+ ModuleActions::Make.new( self, mod, *args ).do
521
+ end
522
+
523
+ # Call the #rebase method of the module.
524
+ #
525
+ # @param [Object] mod The module to use
526
+ def rebase( mod )
527
+ ModuleActions::Rebase.new( self, mod ).do
528
+ end
529
+
530
+ # Call the #reconfigure method of the module.
531
+ #
532
+ # @param [Object] mod The module to use
533
+ def reconfigure( mod )
534
+ ModuleActions::Reconfigure.new( self, mod ).do
535
+ end
536
+
410
537
  end
411
538
 
412
539
 
@@ -525,7 +652,7 @@ module BuildTool; module Commands;
525
652
 
526
653
  def show_help( args = [] )
527
654
  if args.length == 0
528
- @commands.each do |cmd|
655
+ @commands.sort.each do |cmd|
529
656
  say "%-20s: %s" % [ cmd.name, cmd.description ]
530
657
  end
531
658
  else
@@ -542,39 +669,52 @@ module BuildTool; module Commands;
542
669
  return 0
543
670
  end
544
671
 
545
- def load_commands( path, parentmod )
546
- # puts "load_commands( #{path}, #{parentmod} )"
547
- # Load the commands
672
+ def load_commands( path, parentmod, submod = nil )
673
+ logger.debug "load_commands( #{path} #{parentmod.inspect} #{submod.inspect}"
674
+ # Load all available ruby files in path
548
675
  Dir[ "#{path}/*.rb" ].each do |mod|
549
- cmdname = Pathname.new( mod ).basename( '.rb' ).to_s
550
- load_command( path, parentmod, cmdname )
676
+ load "#{mod}"
551
677
  end
552
- end
553
678
 
554
- def load_command( path, parentmod, mod )
555
- # puts "load_command( #{path}, #{parentmod}, #{mod} )"
556
- load "#{path}/#{mod}.rb"
557
- self.instance_eval %{
558
- if #{parentmod}::#{mod.capitalize}.instance_of? ::Module
559
- cmd = #{parentmod}::#{mod.capitalize}.create( self )
560
- else
561
- cmd = #{parentmod}::#{mod.capitalize}.new( self )
679
+ if !submod.nil?
680
+ parentmod = parentmod.const_get( submod )
681
+ end
682
+ # Now look at all constants for candidates
683
+ parentmod.constants.each do |objname|
684
+ # Get the obj
685
+ obj = parentmod.const_get( objname )
686
+ # :TODO: Better solution
687
+ next if [ "Standard", "ModuleBasedCommand", "Base", "SubCommands", "Shell" ].include? objname
688
+ next if ! obj.kind_of? Class
689
+
690
+ tmp = obj
691
+ while tmp.superclass
692
+ if tmp == BuildTool::Commands::SubCommands
693
+ cmd = obj.new( self )
694
+ break if !cmd.applicable?
695
+ if cmd.cmdalias
696
+ parent.add_command( Alias.new( cmd.cmdalias, cmd ) )
697
+ end
698
+ add_command( cmd )
699
+ cmd.load_commands( "#{path}/#{cmd.name}", parentmod, cmd.name.capitalize )
700
+ break
701
+ elsif tmp == BuildTool::Commands::Base
702
+ cmd = obj.new( self )
703
+ break if !cmd.applicable?
704
+ if cmd.cmdalias
705
+ parent.add_command( Alias.new( cmd.cmdalias, cmd ) )
706
+ end
707
+ add_command( cmd )
708
+ break
709
+ end
710
+ tmp = tmp.superclass
562
711
  end
563
- return if !cmd.applicable?
712
+ end
564
713
 
565
- if cmd.cmdalias
566
- parent.add_command( Alias.new( cmd.cmdalias, cmd ) )
567
- end
568
- if cmd.is_a?( SubCommands )
569
- cmd.load_commands( "#{path}/#{mod}", "#{parentmod}::#{mod.capitalize}" )
570
- end
571
- add_command( cmd )
572
- }
573
714
  end
574
715
 
575
716
  end # class SubCommands
576
717
 
577
-
578
718
  #
579
719
  #
580
720
  #
@@ -632,6 +772,10 @@ module BuildTool; module Commands;
632
772
  return 0
633
773
  end
634
774
 
775
+ def fullname
776
+ nil
777
+ end
778
+
635
779
  end # class Shell
636
780
 
637
781