software_smithy 1.1

Sign up to get free protection for your applications and to get access to all the features.
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'