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.
- data/README.rdoc +114 -0
- data/bin/smithy +586 -0
- data/etc/completion/smithy-completion.bash +266 -0
- data/etc/completion/zsh/_smithy +130 -0
- data/etc/smithyrc +36 -0
- data/etc/templates/build/.owners +1 -0
- data/etc/templates/build/build-notes +0 -0
- data/etc/templates/build/dependencies +0 -0
- data/etc/templates/build/rebuild +13 -0
- data/etc/templates/build/relink +2 -0
- data/etc/templates/build/remodule.erb +21 -0
- data/etc/templates/build/retest +6 -0
- data/etc/templates/build/status +0 -0
- data/etc/templates/modulefile.erb +30 -0
- data/etc/templates/package/.check4newver +2 -0
- data/etc/templates/package/.exceptions +3 -0
- data/etc/templates/package/description +18 -0
- data/etc/templates/package/description.markdown +17 -0
- data/etc/templates/package/support +1 -0
- data/etc/templates/package/versions +3 -0
- data/etc/templates/web/all.html.erb +19 -0
- data/etc/templates/web/alphabetical.html.erb +12 -0
- data/etc/templates/web/category.html.erb +74 -0
- data/etc/templates/web/machine_version_table.html.erb +35 -0
- data/etc/templates/web/package.html.erb +53 -0
- data/etc/templates/web/version_list.html.erb +7 -0
- data/etc/templates/web/version_table.html.erb +24 -0
- data/lib/smithy/config.rb +167 -0
- data/lib/smithy/description.rb +276 -0
- data/lib/smithy/file_operations.rb +234 -0
- data/lib/smithy/format.rb +134 -0
- data/lib/smithy/helpers.rb +159 -0
- data/lib/smithy/module_file.rb +224 -0
- data/lib/smithy/package.rb +647 -0
- data/lib/smithy.rb +45 -0
- data/lib/smithy_version.rb +40 -0
- data/man/man1/smithy.1 +262 -0
- data/smithy.rdoc +281 -0
- 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'
|