software_smithy 1.1

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 (39) hide show
  1. data/README.rdoc +114 -0
  2. data/bin/smithy +586 -0
  3. data/etc/completion/smithy-completion.bash +266 -0
  4. data/etc/completion/zsh/_smithy +130 -0
  5. data/etc/smithyrc +36 -0
  6. data/etc/templates/build/.owners +1 -0
  7. data/etc/templates/build/build-notes +0 -0
  8. data/etc/templates/build/dependencies +0 -0
  9. data/etc/templates/build/rebuild +13 -0
  10. data/etc/templates/build/relink +2 -0
  11. data/etc/templates/build/remodule.erb +21 -0
  12. data/etc/templates/build/retest +6 -0
  13. data/etc/templates/build/status +0 -0
  14. data/etc/templates/modulefile.erb +30 -0
  15. data/etc/templates/package/.check4newver +2 -0
  16. data/etc/templates/package/.exceptions +3 -0
  17. data/etc/templates/package/description +18 -0
  18. data/etc/templates/package/description.markdown +17 -0
  19. data/etc/templates/package/support +1 -0
  20. data/etc/templates/package/versions +3 -0
  21. data/etc/templates/web/all.html.erb +19 -0
  22. data/etc/templates/web/alphabetical.html.erb +12 -0
  23. data/etc/templates/web/category.html.erb +74 -0
  24. data/etc/templates/web/machine_version_table.html.erb +35 -0
  25. data/etc/templates/web/package.html.erb +53 -0
  26. data/etc/templates/web/version_list.html.erb +7 -0
  27. data/etc/templates/web/version_table.html.erb +24 -0
  28. data/lib/smithy/config.rb +167 -0
  29. data/lib/smithy/description.rb +276 -0
  30. data/lib/smithy/file_operations.rb +234 -0
  31. data/lib/smithy/format.rb +134 -0
  32. data/lib/smithy/helpers.rb +159 -0
  33. data/lib/smithy/module_file.rb +224 -0
  34. data/lib/smithy/package.rb +647 -0
  35. data/lib/smithy.rb +45 -0
  36. data/lib/smithy_version.rb +40 -0
  37. data/man/man1/smithy.1 +262 -0
  38. data/smithy.rdoc +281 -0
  39. metadata +230 -0
@@ -0,0 +1,647 @@
1
+ # Smithy is freely available under the terms of the BSD license given below. {{{
2
+ #
3
+ # Copyright (c) 2012. UT-BATTELLE, LLC. All rights reserved.
4
+ #
5
+ # Produced by the National Center for Computational Sciences at Oak Ridge
6
+ # National Laboratory. Smithy is a based on SWTools, more information on SWTools
7
+ # can be found at: http://www.olcf.ornl.gov/center-projects/swtools/
8
+ #
9
+ # This product includes software produced by UT-Battelle, LLC under Contract No.
10
+ # DE-AC05-00OR22725 with the Department of Energy.
11
+ #
12
+ # Redistribution and use in source and binary forms, with or without
13
+ # modification, are permitted provided that the following conditions are met:
14
+ #
15
+ # - Redistributions of source code must retain the above copyright notice, this
16
+ # list of conditions and the following disclaimer.
17
+ #
18
+ # - Redistributions in binary form must reproduce the above copyright notice, this
19
+ # list of conditions and the following disclaimer in the documentation and/or
20
+ # other materials provided with the distribution.
21
+ #
22
+ # - Neither the name of the UT-BATTELLE nor the names of its contributors may
23
+ # be used to endorse or promote products derived from this software without
24
+ # specific prior written permission.
25
+ #
26
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
27
+ # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28
+ # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
29
+ # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
30
+ # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31
+ # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
32
+ # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
33
+ # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
34
+ # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
35
+ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36
+ # }}}
37
+
38
+ module Smithy
39
+ class Package
40
+ attr_accessor :arch, :root, :name, :version, :build_name
41
+ attr_accessor :group
42
+
43
+ # Remove root and arch from the path if necessary
44
+ def self.normalize_name(args = {})
45
+ p = args[:name].dup
46
+ if args[:swroot]
47
+ root = File.dirname args[:swroot]
48
+ arch = File.basename args[:swroot]
49
+ else
50
+ root = args[:root]
51
+ arch = args[:arch]
52
+ end
53
+ p.gsub! /\/?#{root}\/?/, ''
54
+ p.gsub! /\/?#{arch}\/?/, ''
55
+ return p
56
+ end
57
+
58
+ def initialize(args = {})
59
+ @root = File.dirname(Smithy::Config.full_root)
60
+ @arch = File.basename(Smithy::Config.full_root)
61
+
62
+ if args[:path].try(:downcase) == 'last'
63
+ @path = Smithy::Config.last_prefix
64
+ else
65
+ @path = Package.normalize_name(:name => args[:path], :root => @root, :arch => @arch)
66
+ end
67
+ @path =~ /(.*)\/(.*)\/(.*)$/
68
+ @name = $1
69
+ @version = $2
70
+ @build_name = $3
71
+ @group = Smithy::Config.file_group
72
+
73
+ @group_writeable = Smithy::Config.group_writeable?
74
+ end
75
+
76
+ def get_binding
77
+ binding
78
+ end
79
+
80
+ PackageFileNames = {
81
+ :exception => ".exceptions",
82
+ :description => "description.markdown",
83
+ :support => "support",
84
+ :versions => "versions" }
85
+
86
+ def package_support_files
87
+ file_list = []
88
+ PackageFileNames.each do |name, file|
89
+ file_list << { :name => name,
90
+ :src => File.join(@@smithy_bin_root, "etc/templates/package", file),
91
+ :dest => File.join(application_directory, file) }
92
+ end
93
+ return file_list
94
+ end
95
+
96
+ BuildFileNames = {
97
+ :notes => "build-notes",
98
+ :dependencies => "dependencies",
99
+ :build => "rebuild",
100
+ :test => "retest",
101
+ :env => "remodule" }
102
+ ExecutableBuildFileNames = [
103
+ BuildFileNames[:build],
104
+ BuildFileNames[:link],
105
+ BuildFileNames[:test],
106
+ BuildFileNames[:env]
107
+ ]
108
+ BuildFileERBs = [
109
+ BuildFileNames[:env] ]
110
+
111
+ def build_support_files
112
+ file_list = []
113
+ BuildFileNames.each do |name, file|
114
+ src = File.join(@@smithy_bin_root, "etc/templates/build", file)
115
+ src += ".erb" if BuildFileERBs.include?(file)
116
+ file_list << { :name => name, :src => src, :dest => File.join(prefix, file) }
117
+ end
118
+ return file_list
119
+ end
120
+
121
+ def group_writeable?
122
+ @group_writeable
123
+ end
124
+
125
+ def valid?
126
+ # Name format validation
127
+ if @name.nil? || @version.nil? || @build_name.nil? || @name.include?('/') || @version.include?('/') || @build_name.include?('/')
128
+ raise "The package name \"#{@path}\" must be of the form: NAME/VERSION/BUILD"
129
+ return false
130
+ end
131
+
132
+ # If good, save as last prefix
133
+ Smithy::Config.save_last_prefix(qualified_name)
134
+ return true
135
+ end
136
+
137
+ def qualified_name
138
+ [@name, @version, @build_name].join('/')
139
+ end
140
+
141
+ def prefix
142
+ File.join(@root, @arch, @name, @version, @build_name)
143
+ end
144
+ def prefix_exists?
145
+ Dir.exist? prefix
146
+ end
147
+ def prefix_exists!
148
+ raise "The package #{prefix} does not exist!" unless prefix_exists?
149
+ end
150
+
151
+ def rebuild_script
152
+ File.join(prefix, BuildFileNames[:build])
153
+ end
154
+ def rebuild_script_exists?
155
+ File.exist?(rebuild_script)
156
+ end
157
+ def rebuild_script_exists!
158
+ raise "The script #{rebuild_script} does not exist!" unless rebuild_script_exists?
159
+ end
160
+
161
+ def retest_script
162
+ File.join(prefix, BuildFileNames[:test])
163
+ end
164
+ def retest_script_exists?
165
+ File.exist?(retest_script)
166
+ end
167
+ def retest_script_exists!
168
+ raise "The script #{retest_script} does not exist!" unless retest_script_exists?
169
+ end
170
+
171
+ def remodule_script
172
+ File.join(prefix, BuildFileNames[:env])
173
+ end
174
+ def remodule_script_exists?
175
+ File.exist?(remodule_script)
176
+ end
177
+ def remodule_script_exists!
178
+ raise "The script #{remodule_script} does not exist!" unless remodule_script_exists?
179
+ end
180
+
181
+ def application_directory
182
+ File.join(@root, @arch, @name)
183
+ end
184
+
185
+ def version_directory
186
+ File.join(@root, @arch, @name, @version)
187
+ end
188
+
189
+ def directories
190
+ [ application_directory, version_directory, prefix ]
191
+ end
192
+
193
+ def software_root
194
+ File.join(@root, @arch)
195
+ end
196
+
197
+ def lock_file
198
+ File.join(prefix, ".lock")
199
+ end
200
+
201
+ def create_lock_file
202
+ if File.exists? lock_file
203
+ notice_fail "#{lock_file} exists, is someone else building this package? If not, use --force or delete and rerun."
204
+ return false
205
+ else
206
+ FileUtils.touch(lock_file)
207
+ FileOperations.set_group(lock_file, group)
208
+ FileOperations.make_group_writable(lock_file) if group_writeable?
209
+ return true
210
+ end
211
+ end
212
+
213
+ def delete_lock_file
214
+ FileUtils.rm_f(lock_file)
215
+ end
216
+
217
+ def run_script(args ={})
218
+ case args[:script]
219
+ when :build
220
+ rebuild_script_exists!
221
+ script = rebuild_script
222
+ notice "Building #{prefix}"
223
+ when :test
224
+ retest_script_exists!
225
+ script = retest_script
226
+ notice "Testing #{prefix}"
227
+ else
228
+ return nil
229
+ end
230
+
231
+ notice_warn "Dry Run! (scripts will not run)" if args[:dry_run]
232
+
233
+ ENV['SMITHY_PREFIX'] = prefix
234
+ ENV['SW_BLDDIR'] = prefix
235
+
236
+ unless args[:disable_logging]
237
+ if args[:log_name]
238
+ log_file_path = File.join(prefix, args[:log_name])
239
+ log_file = File.open(log_file_path, 'w') unless args[:dry_run]
240
+
241
+ FileOperations.set_group(log_file, group)
242
+ FileOperations.make_group_writable(log_file) if group_writeable?
243
+ end
244
+ if args[:dry_run] || log_file != nil
245
+ notice "Logging to #{log_file_path}"
246
+ end
247
+ end
248
+
249
+ unless args[:dry_run]
250
+ if args[:force]
251
+ delete_lock_file
252
+ create_lock_file
253
+ else
254
+ return unless create_lock_file
255
+ end
256
+
257
+ stdout, stderr = '',''
258
+ exit_status = 0
259
+
260
+ begin
261
+ t = Open4.background(script, 0=>'', 1=>stdout, 2=>stderr)
262
+ while t.status do
263
+ process_ouput(stdout, stderr, args[:suppress_stdout], log_file)
264
+ sleep 0.25
265
+ end
266
+
267
+ exit_status = t.exitstatus # this will throw an exception if != 0
268
+ rescue => exception
269
+ exit_status = exception.exitstatus
270
+ end
271
+ # There is usually some leftover output
272
+ process_ouput(stdout, stderr, args[:suppress_stdout], log_file)
273
+
274
+ log_file.close unless log_file.nil?
275
+
276
+ if exit_status == 0
277
+ notice_success "SUCCESS #{prefix}"
278
+ else
279
+ notice_fail "FAILED #{prefix}"
280
+ end
281
+
282
+ case args[:script]
283
+ when :build
284
+ if exit_status == 0
285
+ notice "Setting permissions on installed files"
286
+ FileOperations.set_group prefix, @group, :recursive => true
287
+ FileOperations.make_group_writable prefix, :recursive => true if group_writeable?
288
+ end
289
+ when :test
290
+ end
291
+
292
+ delete_lock_file
293
+ end
294
+ end
295
+
296
+ def download(url)
297
+ curl = '/usr/bin/curl'
298
+ curl = `which curl` unless File.exist? curl
299
+ raise "curl cannot be located, without it files cannot be downloaded" if curl.blank?
300
+
301
+ downloaded_tarball = "#{prefix}/#{File.basename(URI(url).path)}"
302
+ if File.exist?(downloaded_tarball)
303
+ puts "downloaded ".rjust(12).color(:green).bright + downloaded_tarball
304
+ return downloaded_tarball
305
+ else
306
+ puts "download ".rjust(12).color(:green).bright + url
307
+ end
308
+
309
+ args = ['-qf#L']
310
+ args << "--silent" unless $stdout.tty?
311
+ args << '-o'
312
+ args << downloaded_tarball
313
+ args << url
314
+
315
+ if system(curl, *args)
316
+ FileOperations.set_group(downloaded_tarball, group)
317
+ FileOperations.make_group_writable(downloaded_tarball) if group_writeable?
318
+ return downloaded_tarball
319
+ else
320
+ return false
321
+ end
322
+ end
323
+
324
+ def extract(args = {})
325
+ archive = args[:archive]
326
+ temp_dir = File.join(prefix,"tmp")
327
+ source_dir = File.join(prefix,"source")
328
+
329
+ notice "Extracting #{archive} to #{source_dir}"
330
+
331
+ return if args[:dry_run]
332
+
333
+ overwrite = nil
334
+ overwrite = Smithy::Config.global.try(:[], :force)
335
+ if File.exists?(source_dir) &&
336
+ while overwrite.nil? do
337
+ prompt = Readline.readline(" "*FILE_NOTICE_COLUMNS+"Overwrite? (enter \"h\" for help) [ynh] ")
338
+ case prompt.downcase
339
+ when "y"
340
+ overwrite = true
341
+ when "n"
342
+ overwrite = false
343
+ when "h"
344
+ indent = " "*FILE_NOTICE_COLUMNS
345
+ puts indent+"y - yes, delete existing folder and re-extract"
346
+ puts indent+"n - no, do not overwrite"
347
+ puts indent+"h - help, show this help"
348
+ when "q"
349
+ raise "Abort new package"
350
+ end
351
+ end
352
+ else
353
+ overwrite = true
354
+ end
355
+
356
+ if overwrite
357
+ FileUtils.rm_rf temp_dir
358
+ FileUtils.rm_rf source_dir
359
+ FileUtils.mkdir temp_dir
360
+ FileUtils.cd temp_dir
361
+
362
+ magic_bytes = nil
363
+ File.open(archive) do |f|
364
+ magic_bytes = f.read(4)
365
+ end
366
+ case magic_bytes
367
+ when /^PK\003\004/ # .zip archive
368
+ `unzip #{archive}`
369
+ when /^\037\213/, /^BZh/, /^\037\235/ # gzip/bz2/compress compressed
370
+ `tar xf #{archive}`
371
+ end
372
+
373
+ extracted_files = Dir.glob('*')
374
+ if extracted_files.count == 1
375
+ FileUtils.mv extracted_files.first, source_dir
376
+ else
377
+ FileUtils.cd prefix
378
+ FileUtils.mv temp_dir, source_dir
379
+ end
380
+
381
+ FileUtils.rm_rf temp_dir
382
+
383
+ FileOperations.set_group source_dir, @group, :recursive => true
384
+ FileOperations.make_group_writable source_dir, :recursive => true if group_writeable?
385
+ end
386
+ end
387
+
388
+ def create(args = {})
389
+ notice "New #{args[:stub] ? "stub " : ""}#{prefix}"
390
+ notice_warn "Dry Run! (no files will be created or changed)" if args[:dry_run]
391
+ options = {:noop => false, :verbose => false}
392
+ options[:noop] = true if args[:dry_run]
393
+
394
+ if args[:stub]
395
+ [application_directory].each do |dir|
396
+ FileOperations.make_directory dir, options
397
+ FileOperations.set_group dir, group, options
398
+ FileOperations.make_group_writable dir, options if group_writeable?
399
+ end
400
+
401
+ version_table_file = File.join(application_directory, ".versions")
402
+ version_table = YAML.load_file(version_table_file).stringify_keys rescue {}
403
+ version_table.merge!({version => build_name})
404
+
405
+ FileOperations.install_from_string version_table.to_yaml, version_table_file, options.merge({:force => true})
406
+ FileOperations.set_group version_table_file, group, options
407
+ FileOperations.make_group_writable version_table_file, options if group_writeable?
408
+ else
409
+
410
+ directories.each do |dir|
411
+ #if dir == prefix
412
+ FileOperations.make_directory dir, options
413
+ FileOperations.set_group dir, group, options
414
+ FileOperations.make_group_writable dir, options if group_writeable?
415
+ #end
416
+ end
417
+
418
+ all_files = build_support_files
419
+ all_files = package_support_files + all_files if args[:web] || args[:stub]
420
+
421
+ all_files.each do |file|
422
+ if file[:src] =~ /\.erb$/
423
+ FileOperations.render_erb :erb => file[:src], :binding => get_binding, :options => options, :destination => file[:dest]
424
+ elsif file[:name] == :description
425
+ d = Description.new(:package => self)
426
+ original_dest = file[:dest]
427
+ file[:dest] = d.description_file_path
428
+ FileOperations.make_directory(d.path, options) if d.global_description
429
+ FileOperations.install_file(file[:src], file[:dest], options)
430
+ FileOperations.make_symlink(file[:dest], original_dest, options) if d.global_description
431
+ else
432
+ FileOperations.install_file file[:src], file[:dest], options
433
+ end
434
+
435
+ FileOperations.set_group file[:dest], group, options
436
+ FileOperations.make_group_writable file[:dest], options if group_writeable?
437
+ FileOperations.make_executable file[:dest], options if file[:dest] =~ /(#{ExecutableBuildFileNames.join('|')})/
438
+ end
439
+
440
+ end
441
+ end
442
+
443
+ def module_load_prgenv
444
+ output = ""
445
+ ModuleFile::Environments.each do |e|
446
+ if build_name =~ e[:regex]
447
+ output = "module load #{e[:prg_env]}"
448
+ break
449
+ end
450
+ end
451
+ return output
452
+ end
453
+
454
+ def repair(args = {})
455
+ notice "Repair #{prefix} #{args[:dry_run] ? "(dry run)" : ""}"
456
+ options = {:noop => false, :verbose => false}
457
+ options[:noop] = true if args[:dry_run]
458
+ options[:verbose] = true if args[:dry_run] || args[:verbose]
459
+
460
+ missing_package = []
461
+ missing_build = []
462
+
463
+ notice "Checking support files"
464
+ (package_support_files+build_support_files).each do |file|
465
+ f = file[:dest]
466
+
467
+ if File.exists?(f)
468
+ if File.size(f) == 0
469
+ puts "empty ".rjust(12).color(:yellow) + f
470
+ else
471
+ puts "exists ".rjust(12).bright + f
472
+ end
473
+ FileOperations.make_executable file[:dest], options if f =~ /#{ExecutableBuildFileNames.join('|')}/
474
+ else
475
+ puts "missing ".rjust(12).color(:red) + f
476
+
477
+ missing_package << File.basename(f) if PackageFileNames.values.include?(File.basename(f))
478
+ missing_build << File.basename(f) if BuildFileNames.values.include?(File.basename(f))
479
+ end
480
+ end
481
+
482
+ notice "Creating missing files" if !missing_package.empty? || !missing_build.empty?
483
+
484
+ if !missing_package.empty?
485
+ package_support_files.each do |file|
486
+ if missing_package.include?(file[:name])
487
+ FileOperations.install_file file[:src], file[:dest], options
488
+ FileOperations.set_group file[:dest], group, options
489
+ FileOperations.make_group_writable file[:dest], options if group_writeable?
490
+ end
491
+ end
492
+ end
493
+
494
+ if !missing_build.empty?
495
+ build_support_files.each do |file|
496
+ if missing_build.include?(file[:name])
497
+ FileOperations.install_file file[:src], file[:dest], options
498
+ FileOperations.set_group file[:dest], group, options
499
+ FileOperations.make_group_writable file[:dest], options if group_writeable?
500
+ end
501
+ end
502
+ end
503
+
504
+ notice "Setting permissions for #{prefix}"
505
+
506
+ FileOperations.set_group prefix, group, options.merge(:recursive => true)
507
+ FileOperations.make_group_writable prefix, options.merge(:recursive => true) if group_writeable?
508
+
509
+ [version_directory, application_directory].each do |dir|
510
+ FileOperations.set_group dir, group, options
511
+ FileOperations.make_group_writable dir, options if group_writeable?
512
+ end
513
+ end
514
+
515
+ def alternate_builds
516
+ Package.alternate_builds(self.version_directory)
517
+ end
518
+
519
+ def self.alternate_builds(version_directory)
520
+ version = File.basename(version_directory)
521
+ builds = Dir.glob(version_directory+"/*")
522
+ # Delete anything that isn't a directory
523
+ builds.reject! { |b| ! File.directory?(b) }
524
+ builds.reject! { |b| b =~ /#{ModuleFile::PackageModulePathName}/ }
525
+ # Get the directory name from the full path
526
+ builds.collect! { |b| File.basename(b) }
527
+
528
+ stubbed_builds = YAML.load_file(File.join(File.dirname(version_directory), ".versions")).stringify_keys rescue {}
529
+ if stubbed_builds[version]
530
+ if stubbed_builds[version].class == String
531
+ builds += [ stubbed_builds[version] ]
532
+ else
533
+ builds += stubbed_builds[version]
534
+ end
535
+ end
536
+ builds.uniq!
537
+
538
+ return builds.sort
539
+ end
540
+
541
+ def alternate_versions
542
+ Package.alternate_builds(self.application_directory)
543
+ end
544
+
545
+ def self.alternate_versions(application_directory)
546
+ versions = Dir.glob(application_directory+"/*")
547
+ # Delete anything that isn't a directory
548
+ versions.reject! { |b| ! File.directory?(b) }
549
+ # Get the directory name from the full path
550
+ versions.collect! { |b| File.basename(b) }
551
+
552
+ stubbed_builds = YAML.load_file(File.join(application_directory, ".versions")).stringify_keys rescue {}
553
+ versions += stubbed_builds.keys
554
+ versions.uniq!
555
+
556
+ return versions.sort
557
+ end
558
+
559
+ def publishable?
560
+ Description.publishable?(application_directory)
561
+ end
562
+
563
+ def self.all(args = {})
564
+ # Array of full paths to rebuild scripts
565
+ software = Dir.glob(args[:root]+"/*/*/*/#{BuildFileNames[:build]}")
566
+ # Remove rebuild from each path
567
+ software.collect!{|s| s.gsub(/\/#{BuildFileNames[:build]}$/, '')}
568
+ #TODO allow sorting?
569
+ software.sort!
570
+ end
571
+
572
+ def self.all_web(args = {})
573
+ # Find all software with descriptions
574
+ descriptions_dir = Smithy::Config.full_root
575
+ descriptions_dir = Smithy::Config.descriptions_root if Smithy::Config.descriptions_root
576
+ software = Dir.glob(descriptions_dir+"/*/description*")
577
+
578
+ software.collect!{|s| File.dirname(s) }
579
+ software.uniq!
580
+
581
+ # Remove any with noweb in their exceptions file
582
+ software.reject! do |s|
583
+ ! Description.publishable?(s)
584
+ end
585
+ software.sort!
586
+ return software
587
+ end
588
+
589
+ def self.create_stubs_from_modules(stub_packages, system_module_defaults, options = {})
590
+ notice "Generating stubs for the following modules:"
591
+ Format.print_column_list(stub_packages)
592
+ proceed = nil
593
+ while proceed.nil? do
594
+ prompt = Readline.readline("Generate the above packages? [yn] ")
595
+ case prompt.downcase
596
+ when "y"
597
+ proceed = true
598
+ when "n"
599
+ proceed = false
600
+ end
601
+ end
602
+
603
+ raise "aborting package generation" if proceed == false
604
+
605
+ stub_packages.each do |module_name|
606
+ name, version = module_name.split("/")
607
+ p = Package.new :path => "#{name}/#{version}/universal"
608
+ p.create :stub => true, :dry_run => options[:"dry-run"]
609
+
610
+ default_module = ""
611
+ possible_defaults = system_module_defaults.select{ |m| m =~ %r{\/#{name}\/} }
612
+ defaulted = possible_defaults.select{ |m| m =~ %r{\(default\)$} }
613
+ if defaulted.size > 0
614
+ default_module = defaulted.first
615
+ else
616
+ default_module = possible_defaults.last
617
+ end
618
+
619
+ help_content = modulehelp(name)
620
+ #help_content.gsub!(/^[\t ]+/, '')
621
+ help_content.gsub!(/^--* Module Specific Help.*-$/, '')
622
+ help_content.gsub!(/^===================================================================$/, '')
623
+ help_content.gsub!(/\A\n*/, '')
624
+ help_content = """# #{name}
625
+
626
+ Categories:
627
+
628
+ ## Description
629
+
630
+ The following information is available by running `module help #{name}`
631
+
632
+ ~~~~~~~~~~~~~~~~~~~~~
633
+ #{help_content}
634
+ ~~~~~~~~~~~~~~~~~~~~~
635
+ """
636
+
637
+ help_dest = File.join(p.application_directory, "description.markdown")
638
+
639
+ ops = {:noop => options[:"dry-run"] ? true : false}
640
+ FileOperations.install_from_string(help_content, help_dest, ops)
641
+ FileOperations.set_group help_dest, p.group, ops
642
+ FileOperations.make_group_writable help_dest, ops if p.group_writeable?
643
+ end
644
+ end
645
+
646
+ end
647
+ end
data/lib/smithy.rb ADDED
@@ -0,0 +1,45 @@
1
+ # Smithy is freely available under the terms of the BSD license given below. {{{
2
+ #
3
+ # Copyright (c) 2012. UT-BATTELLE, LLC. All rights reserved.
4
+ #
5
+ # Produced by the National Center for Computational Sciences at Oak Ridge
6
+ # National Laboratory. Smithy is a based on SWTools, more information on SWTools
7
+ # can be found at: http://www.olcf.ornl.gov/center-projects/swtools/
8
+ #
9
+ # This product includes software produced by UT-Battelle, LLC under Contract No.
10
+ # DE-AC05-00OR22725 with the Department of Energy.
11
+ #
12
+ # Redistribution and use in source and binary forms, with or without
13
+ # modification, are permitted provided that the following conditions are met:
14
+ #
15
+ # - Redistributions of source code must retain the above copyright notice, this
16
+ # list of conditions and the following disclaimer.
17
+ #
18
+ # - Redistributions in binary form must reproduce the above copyright notice, this
19
+ # list of conditions and the following disclaimer in the documentation and/or
20
+ # other materials provided with the distribution.
21
+ #
22
+ # - Neither the name of the UT-BATTELLE nor the names of its contributors may
23
+ # be used to endorse or promote products derived from this software without
24
+ # specific prior written permission.
25
+ #
26
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
27
+ # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28
+ # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
29
+ # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
30
+ # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31
+ # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
32
+ # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
33
+ # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
34
+ # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
35
+ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36
+ # }}}
37
+
38
+ require 'smithy_version'
39
+ require 'smithy/config'
40
+ require 'smithy/helpers'
41
+ require 'smithy/format'
42
+ require 'smithy/package'
43
+ require 'smithy/module_file'
44
+ require 'smithy/description'
45
+ require 'smithy/file_operations'