scout-essentials 1.0.0

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 (107) hide show
  1. checksums.yaml +7 -0
  2. data/.document +5 -0
  3. data/.vimproject +78 -0
  4. data/Gemfile +14 -0
  5. data/LICENSE.txt +20 -0
  6. data/README.rdoc +18 -0
  7. data/Rakefile +47 -0
  8. data/VERSION +1 -0
  9. data/lib/scout/cmd.rb +348 -0
  10. data/lib/scout/concurrent_stream.rb +284 -0
  11. data/lib/scout/config.rb +168 -0
  12. data/lib/scout/exceptions.rb +77 -0
  13. data/lib/scout/indiferent_hash/case_insensitive.rb +30 -0
  14. data/lib/scout/indiferent_hash/options.rb +115 -0
  15. data/lib/scout/indiferent_hash.rb +96 -0
  16. data/lib/scout/log/color.rb +224 -0
  17. data/lib/scout/log/color_class.rb +269 -0
  18. data/lib/scout/log/fingerprint.rb +69 -0
  19. data/lib/scout/log/progress/report.rb +244 -0
  20. data/lib/scout/log/progress/util.rb +173 -0
  21. data/lib/scout/log/progress.rb +106 -0
  22. data/lib/scout/log/trap.rb +107 -0
  23. data/lib/scout/log.rb +441 -0
  24. data/lib/scout/meta_extension.rb +100 -0
  25. data/lib/scout/misc/digest.rb +63 -0
  26. data/lib/scout/misc/filesystem.rb +25 -0
  27. data/lib/scout/misc/format.rb +255 -0
  28. data/lib/scout/misc/helper.rb +31 -0
  29. data/lib/scout/misc/insist.rb +56 -0
  30. data/lib/scout/misc/monitor.rb +66 -0
  31. data/lib/scout/misc/system.rb +73 -0
  32. data/lib/scout/misc.rb +10 -0
  33. data/lib/scout/named_array.rb +138 -0
  34. data/lib/scout/open/lock/lockfile.rb +587 -0
  35. data/lib/scout/open/lock.rb +68 -0
  36. data/lib/scout/open/remote.rb +135 -0
  37. data/lib/scout/open/stream.rb +491 -0
  38. data/lib/scout/open/util.rb +244 -0
  39. data/lib/scout/open.rb +170 -0
  40. data/lib/scout/path/find.rb +204 -0
  41. data/lib/scout/path/tmpfile.rb +8 -0
  42. data/lib/scout/path/util.rb +127 -0
  43. data/lib/scout/path.rb +51 -0
  44. data/lib/scout/persist/open.rb +17 -0
  45. data/lib/scout/persist/path.rb +15 -0
  46. data/lib/scout/persist/serialize.rb +157 -0
  47. data/lib/scout/persist.rb +104 -0
  48. data/lib/scout/resource/open.rb +8 -0
  49. data/lib/scout/resource/path.rb +80 -0
  50. data/lib/scout/resource/produce/rake.rb +69 -0
  51. data/lib/scout/resource/produce.rb +151 -0
  52. data/lib/scout/resource/scout.rb +3 -0
  53. data/lib/scout/resource/software.rb +178 -0
  54. data/lib/scout/resource/util.rb +59 -0
  55. data/lib/scout/resource.rb +40 -0
  56. data/lib/scout/simple_opt/accessor.rb +54 -0
  57. data/lib/scout/simple_opt/doc.rb +126 -0
  58. data/lib/scout/simple_opt/get.rb +57 -0
  59. data/lib/scout/simple_opt/parse.rb +67 -0
  60. data/lib/scout/simple_opt/setup.rb +26 -0
  61. data/lib/scout/simple_opt.rb +5 -0
  62. data/lib/scout/tmpfile.rb +129 -0
  63. data/lib/scout-essentials.rb +10 -0
  64. data/scout-essentials.gemspec +143 -0
  65. data/share/color/color_names +507 -0
  66. data/share/color/diverging_colors.hex +12 -0
  67. data/share/software/install_helpers +523 -0
  68. data/test/scout/indiferent_hash/test_case_insensitive.rb +16 -0
  69. data/test/scout/indiferent_hash/test_options.rb +46 -0
  70. data/test/scout/log/test_color.rb +0 -0
  71. data/test/scout/log/test_progress.rb +108 -0
  72. data/test/scout/misc/test_digest.rb +30 -0
  73. data/test/scout/misc/test_filesystem.rb +30 -0
  74. data/test/scout/misc/test_insist.rb +13 -0
  75. data/test/scout/misc/test_system.rb +21 -0
  76. data/test/scout/open/test_lock.rb +52 -0
  77. data/test/scout/open/test_remote.rb +25 -0
  78. data/test/scout/open/test_stream.rb +676 -0
  79. data/test/scout/open/test_util.rb +73 -0
  80. data/test/scout/path/test_find.rb +110 -0
  81. data/test/scout/path/test_util.rb +22 -0
  82. data/test/scout/persist/test_open.rb +37 -0
  83. data/test/scout/persist/test_path.rb +37 -0
  84. data/test/scout/persist/test_serialize.rb +114 -0
  85. data/test/scout/resource/test_path.rb +58 -0
  86. data/test/scout/resource/test_produce.rb +94 -0
  87. data/test/scout/resource/test_software.rb +24 -0
  88. data/test/scout/resource/test_util.rb +38 -0
  89. data/test/scout/simple_opt/test_doc.rb +16 -0
  90. data/test/scout/simple_opt/test_get.rb +11 -0
  91. data/test/scout/simple_opt/test_parse.rb +10 -0
  92. data/test/scout/simple_opt/test_setup.rb +77 -0
  93. data/test/scout/test_cmd.rb +85 -0
  94. data/test/scout/test_concurrent_stream.rb +29 -0
  95. data/test/scout/test_config.rb +66 -0
  96. data/test/scout/test_indiferent_hash.rb +26 -0
  97. data/test/scout/test_log.rb +32 -0
  98. data/test/scout/test_meta_extension.rb +80 -0
  99. data/test/scout/test_misc.rb +6 -0
  100. data/test/scout/test_named_array.rb +43 -0
  101. data/test/scout/test_open.rb +146 -0
  102. data/test/scout/test_path.rb +54 -0
  103. data/test/scout/test_persist.rb +186 -0
  104. data/test/scout/test_resource.rb +26 -0
  105. data/test/scout/test_tmpfile.rb +53 -0
  106. data/test/test_helper.rb +50 -0
  107. metadata +247 -0
@@ -0,0 +1,244 @@
1
+ module Open
2
+ GREP_CMD = begin
3
+ if ENV["GREP_CMD"]
4
+ ENV["GREP_CMD"]
5
+ elsif File.exist?('/bin/grep')
6
+ "/bin/grep"
7
+ elsif File.exist?('/usr/bin/grep')
8
+ "/usr/bin/grep"
9
+ else
10
+ "grep"
11
+ end
12
+ end
13
+
14
+ def self.grep(stream, grep, invert = false, fixed = nil)
15
+ case
16
+ when Array === grep
17
+ TmpFile.with_file(grep * "\n", false) do |f|
18
+ if FalseClass === fixed
19
+ CMD.cmd("#{GREP_CMD} #{invert ? '-v' : ''} -", "-f" => f, :in => stream, :pipe => true, :post => proc{FileUtils.rm f})
20
+ else
21
+ CMD.cmd("#{GREP_CMD} #{invert ? '-v' : ''} -", "-w" => true, "-F" => true, "-f" => f, :in => stream, :pipe => true, :post => proc{FileUtils.rm f})
22
+ end
23
+ end
24
+ else
25
+ CMD.cmd("#{GREP_CMD} #{invert ? '-v ' : ''} '#{grep}' -", :in => stream, :pipe => true, :post => proc{begin stream.force_close; rescue Exception; end if stream.respond_to?(:force_close)})
26
+ end
27
+ end
28
+
29
+ def self.gzip_pipe(file)
30
+ Open.gzip?(file) ? "<(gunzip -c '#{file}')" : "'#{file}'"
31
+ end
32
+
33
+ def self.bgunzip(stream)
34
+ Bgzf.setup stream
35
+ end
36
+
37
+ def self.gunzip(stream)
38
+ CMD.cmd('zcat', :in => stream, :pipe => true, :no_fail => true, :no_wait => true)
39
+ end
40
+
41
+ def self.gzip(stream)
42
+ CMD.cmd('gzip', :in => stream, :pipe => true, :no_fail => true, :no_wait => true)
43
+ end
44
+
45
+ def self.bgzip(stream)
46
+ CMD.cmd('bgzip', :in => stream, :pipe => true, :no_fail => true, :no_wait => true)
47
+ end
48
+
49
+ def self.unzip(stream)
50
+ TmpFile.with_file(stream.read) do |filename|
51
+ StringIO.new(CMD.cmd("unzip '{opt}' #{filename}", "-p" => true, :pipe => true).read)
52
+ end
53
+ end
54
+
55
+ # Questions
56
+ def self.gzip?(file)
57
+ file = file.find if Path === file
58
+ !! (file =~ /\.gz$/)
59
+ end
60
+
61
+ def self.bgzip?(file)
62
+ file = file.find if Path === file
63
+ !! (file =~ /\.bgz$/)
64
+ end
65
+
66
+ def self.zip?(file)
67
+ file = file.find if Path === file
68
+ !! (file =~ /\.zip$/)
69
+ end
70
+
71
+ def self.is_stream?(obj)
72
+ IO === obj || StringIO === obj
73
+ end
74
+
75
+ def self.has_stream?(obj)
76
+ obj.respond_to?(:stream)
77
+ end
78
+
79
+
80
+ def self.notify_write(file)
81
+ begin
82
+ notification_file = file + '.notify'
83
+ if Open.exists? notification_file
84
+ key = Open.read(notification_file).strip
85
+ key = nil if key.empty?
86
+ if key && key.include?("@")
87
+ to = from = key
88
+ subject = "Wrote " << file
89
+ message = "Content attached"
90
+ Misc.send_email(from, to, subject, message, :files => [file])
91
+ else
92
+ Misc.notify("Wrote " << file, nil, key)
93
+ end
94
+ Open.rm notification_file
95
+ end
96
+ rescue
97
+ Log.exception $!
98
+ Log.warn "Error notifying write of #{ file }"
99
+ end
100
+ end
101
+
102
+ def self.broken_link?(path)
103
+ File.symlink?(path) && ! File.exist?(File.readlink(path))
104
+ end
105
+
106
+ def self.directory?(file)
107
+ file = file.find if Path === file
108
+ File.directory?(file)
109
+ end
110
+
111
+ def self.exists?(file)
112
+ file = file.find if Path === file
113
+ File.exist?(file)
114
+ end
115
+ class << self; alias exist? exists? end
116
+
117
+ def self.mv(source, target, options = {})
118
+ target = target.find if Path === target
119
+ source = source.find if Path === source
120
+ FileUtils.mkdir_p File.dirname(target) unless File.exist?(File.dirname(target))
121
+ tmp_target = File.join(File.dirname(target), '.tmp_mv.' + File.basename(target))
122
+ FileUtils.mv source, tmp_target
123
+ FileUtils.mv tmp_target, target
124
+ return nil
125
+ end
126
+
127
+ def self.rm(file)
128
+ FileUtils.rm(file) if File.exist?(file) || Open.broken_link?(file)
129
+ end
130
+
131
+ def self.rm_rf(file)
132
+ FileUtils.rm_rf(file)
133
+ end
134
+
135
+ def self.touch(file)
136
+ FileUtils.touch(file)
137
+ end
138
+
139
+ def self.mkdir(target)
140
+ target = target.find if Path === target
141
+ if ! File.exist?(target)
142
+ FileUtils.mkdir_p target
143
+ end
144
+ end
145
+
146
+ def self.writable?(path)
147
+ path = path.find if Path === path
148
+ if File.symlink?(path)
149
+ File.writable?(File.dirname(path))
150
+ elsif File.exist?(path)
151
+ File.writable?(path)
152
+ else
153
+ File.writable?(File.dirname(File.expand_path(path)))
154
+ end
155
+ end
156
+
157
+ def self.ctime(file)
158
+ file = file.find if Path === file
159
+ File.ctime(file)
160
+ end
161
+
162
+ def self.realpath(file)
163
+ file = file.find if Path === file
164
+ Pathname.new(File.expand_path(file)).realpath.to_s
165
+ end
166
+
167
+ def self.mtime(file)
168
+ file = file.find if Path === file
169
+ begin
170
+ if File.symlink?(file) || File.stat(file).nlink > 1
171
+ if File.exist?(file + '.info') && defined?(Step)
172
+ done = Persist.load(file + '.info', Step::SERIALIZER)[:done]
173
+ return done if done
174
+ end
175
+
176
+ file = Pathname.new(file).realpath.to_s
177
+ end
178
+ return nil unless File.exist?(file)
179
+ File.mtime(file)
180
+ rescue
181
+ nil
182
+ end
183
+ end
184
+
185
+ def self.cp(source, target, options = {})
186
+ source = source.find if Path === source
187
+ target = target.find if Path === target
188
+
189
+ FileUtils.mkdir_p File.dirname(target) unless File.exist?(File.dirname(target))
190
+ FileUtils.rm_rf target if File.exist?(target)
191
+ FileUtils.cp_r source, target
192
+ end
193
+
194
+
195
+ def self.ln_s(source, target, options = {})
196
+ source = source.find if Path === source
197
+ target = target.find if Path === target
198
+
199
+ target = File.join(target, File.basename(source)) if File.directory? target
200
+ FileUtils.mkdir_p File.dirname(target) unless File.exist?(File.dirname(target))
201
+ FileUtils.rm target if File.exist?(target)
202
+ FileUtils.rm target if File.symlink?(target)
203
+ FileUtils.ln_s source, target
204
+ end
205
+
206
+ def self.ln(source, target, options = {})
207
+ source = source.find if Path === source
208
+ target = target.find if Path === target
209
+ source = File.realpath(source) if File.symlink?(source)
210
+
211
+ FileUtils.mkdir_p File.dirname(target) unless File.exist?(File.dirname(target))
212
+ FileUtils.rm target if File.exist?(target)
213
+ FileUtils.rm target if File.symlink?(target)
214
+ FileUtils.ln source, target
215
+ end
216
+
217
+ def self.ln_h(source, target, options = {})
218
+ source = source.find if Path === source
219
+ target = target.find if Path === target
220
+
221
+ FileUtils.mkdir_p File.dirname(target) unless File.exist?(File.dirname(target))
222
+ FileUtils.rm target if File.exist?(target)
223
+ begin
224
+ CMD.cmd("ln -L '#{ source }' '#{ target }'")
225
+ rescue ProcessFailed
226
+ Log.debug "Could not hard link #{source} and #{target}: #{$!.message.gsub("\n", '. ')}"
227
+ CMD.cmd("cp -L '#{ source }' '#{ target }'")
228
+ end
229
+ end
230
+
231
+ def self.link(source, target, options = {})
232
+ begin
233
+ Open.ln(source, target, options)
234
+ rescue
235
+ Open.ln_s(source, target, options)
236
+ end
237
+ nil
238
+ end
239
+
240
+ def self.list(file)
241
+ file = file.produce_and_find if Path === file
242
+ Open.read(file).split("\n")
243
+ end
244
+ end
data/lib/scout/open.rb ADDED
@@ -0,0 +1,170 @@
1
+ require_relative 'tmpfile'
2
+ require_relative 'path'
3
+ require_relative 'cmd'
4
+
5
+ require_relative 'open/stream'
6
+ require_relative 'open/util'
7
+ require_relative 'open/remote'
8
+ require_relative 'open/lock'
9
+
10
+ module Open
11
+ module NamedStream
12
+ attr_accessor :filename
13
+
14
+ def digest_str
15
+ if Path === filename && ! filename.located?
16
+ filename
17
+ else
18
+ Misc.file_md5(filename)
19
+ end
20
+ end
21
+ end
22
+
23
+ def self.get_stream(file, mode = 'r', options = {})
24
+ return file if Open.is_stream?(file)
25
+ return file.stream if Open.has_stream?(file)
26
+ file = file.find if Path === file
27
+
28
+ return Open.ssh(file, options) if Open.ssh?(file)
29
+ return Open.wget(file, options) if Open.remote?(file)
30
+
31
+ File.open(file, mode)
32
+ end
33
+
34
+ def self.file_open(file, grep = false, mode = 'r', invert_grep = false, options = {})
35
+ Open.mkdir File.dirname(file) if mode.include? 'w'
36
+
37
+ stream = get_stream(file, mode, options)
38
+
39
+ if grep
40
+ grep(stream, grep, invert_grep)
41
+ else
42
+ stream
43
+ end
44
+ end
45
+
46
+ def self.file_write(file, content, mode = 'w')
47
+ File.open(file, mode) do |f|
48
+ begin
49
+ f.flock(File::LOCK_EX)
50
+ f.write content
51
+ f.flock(File::LOCK_UN)
52
+ ensure
53
+ f.close unless f.closed?
54
+ end
55
+ end
56
+ end
57
+
58
+ def self.open(file, options = {})
59
+ if IO === file || StringIO === file
60
+ if block_given?
61
+ res = yield file, options
62
+ file.close
63
+ return res
64
+ else
65
+ return file
66
+ end
67
+ end
68
+
69
+ options = IndiferentHash.add_defaults options, :noz => false, :mode => 'r'
70
+
71
+ mode = IndiferentHash.process_options options, :mode
72
+
73
+ options[:noz] = true if mode.include? "w"
74
+
75
+ io = file_open(file, options[:grep], mode, options[:invert_grep], options)
76
+
77
+ io = unzip(io) if ((String === file and zip?(file)) and not options[:noz]) or options[:zip]
78
+ io = gunzip(io) if ((String === file and gzip?(file)) and not options[:noz]) or options[:gzip]
79
+ io = bgunzip(io) if ((String === file and bgzip?(file)) and not options[:noz]) or options[:bgzip]
80
+
81
+ io.extend NamedStream
82
+ io.filename = file
83
+
84
+ if block_given?
85
+ res = nil
86
+ begin
87
+ res = yield(io)
88
+ rescue DontClose
89
+ res = $!.payload
90
+ rescue Exception
91
+ io.abort $! if io.respond_to? :abort
92
+ io.join if io.respond_to? :join
93
+ raise $!
94
+ ensure
95
+ io.close if io.respond_to? :close and not io.closed?
96
+ io.join if io.respond_to? :join
97
+ end
98
+ res
99
+ else
100
+ io
101
+ end
102
+ end
103
+
104
+ def self.read(file, options = {}, &block)
105
+ open(file, options) do |f|
106
+ if block_given?
107
+ res = []
108
+ while not f.eof?
109
+ l = f.gets
110
+ l = Misc.fixutf8(l) unless options[:nofix]
111
+ res << yield(l)
112
+ end
113
+ res
114
+ else
115
+ if options[:nofix]
116
+ f.read
117
+ else
118
+ Misc.fixutf8(f.read)
119
+ end
120
+ end
121
+ end
122
+ end
123
+
124
+ def self.write(file, content = nil, options = {})
125
+ options = IndiferentHash.add_defaults options, :mode => 'w'
126
+
127
+ file = file.find(options[:where]) if Path === file
128
+ mode = IndiferentHash.process_options options, :mode
129
+
130
+ FileUtils.mkdir_p File.dirname(file)
131
+
132
+ case
133
+ when block_given?
134
+ begin
135
+ f = File.open(file, mode)
136
+ begin
137
+ yield f
138
+ ensure
139
+ f.close unless f.closed?
140
+ end
141
+ rescue Exception
142
+ FileUtils.rm file if File.exist? file
143
+ raise $!
144
+ end
145
+ when content.nil?
146
+ file_write(file, "", mode)
147
+ when String === content
148
+ file_write(file, content, mode)
149
+ when (IO === content || StringIO === content)
150
+ begin
151
+ File.open(file, mode) do |f|
152
+ f.flock(File::LOCK_EX)
153
+ while block = content.read(Open::BLOCK_SIZE)
154
+ f.write block
155
+ end
156
+ f.flock(File::LOCK_UN)
157
+ end
158
+ rescue Exception
159
+ FileUtils.rm_rf file if File.exist? file
160
+ raise $!
161
+ end
162
+ content.close unless content.closed?
163
+ content.join if content.respond_to? :join
164
+ else
165
+ raise "Content unknown #{Log.fingerprint content}"
166
+ end
167
+
168
+ notify_write(file)
169
+ end
170
+ end
@@ -0,0 +1,204 @@
1
+ require_relative '../indiferent_hash'
2
+ module Path
3
+
4
+ def self.caller_lib_dir(file = nil, relative_to = ['lib', 'bin'])
5
+
6
+ if file.nil?
7
+ caller_dup = caller.dup
8
+ while file = caller_dup.shift
9
+ break unless file =~ /(?:scout|rbbt)\/(?:resource\.rb|workflow\.rb)/ or
10
+ file =~ /(?:scout|rbbt)\/(?:.*\/)?path\.rb/ or
11
+ file =~ /(?:scout|rbbt)\/(?:.*\/)?path\/(?:find|refactor|util)\.rb/ or
12
+ file =~ /(?:scout|rbbt)\/persist.rb/ or
13
+ file =~ /scout\/resource\/produce.rb/ or
14
+ file =~ /modules\/rbbt-util/
15
+ end
16
+ return nil if file.nil?
17
+ file = file.sub(/\.rb[^\w].*/,'.rb')
18
+ end
19
+
20
+ relative_to = [relative_to] unless Array === relative_to
21
+ file = File.expand_path(file)
22
+ return Path.setup(file) if relative_to.select{|d| File.exist? File.join(file, d)}.any?
23
+
24
+ while file != '/'
25
+ dir = File.dirname file
26
+
27
+ return dir if relative_to.select{|d| File.exist? File.join(dir, d)}.any?
28
+
29
+ file = File.dirname file
30
+ end
31
+
32
+ return nil
33
+ end
34
+
35
+ def self.follow(path, map, map_name = nil)
36
+ file = map.sub('{PKGDIR}', path.pkgdir.respond_to?(:pkgdir) ? path.pkgdir.pkgdir || Path.default_pkgdir : path.pkgdir || Path.default_pkgdir).
37
+ sub('{HOME}', ENV["HOME"]).
38
+ sub('{RESOURCE}', path.pkgdir.to_s).
39
+ sub('{PWD}', FileUtils.pwd).
40
+ sub('{TOPLEVEL}', path._toplevel).
41
+ sub('{SUBPATH}', path._subpath).
42
+ sub('{BASENAME}', File.basename(path)).
43
+ sub('{PATH}', path).
44
+ sub('{LIBDIR}', path.libdir || (path.pkgdir.respond_to?(:libdir) && path.pkgdir.libdir) || Path.caller_lib_dir || "NOLIBDIR").
45
+ sub('{MAPNAME}', map_name.to_s).
46
+ sub('{REMOVE}/', '').
47
+ sub('{REMOVE}', '').gsub(/\/+/,'/')
48
+
49
+ while true
50
+ file.gsub!(/\{(.+)(?<!\\)\/(.+)(?<!\\)\/(.+)\}/) do |m|
51
+ key, orig, replace = m.split(/(?<!\\)\//).collect{|p| p.gsub('\/','/') }
52
+ key_text = follow(path, "#{key}}", map_name)
53
+ key_text[orig] = replace[0..-2] if key_text.include?(orig)
54
+ key_text
55
+ end || break
56
+ end
57
+
58
+ file
59
+ end
60
+
61
+ def self.path_maps
62
+ @@path_maps ||= IndiferentHash.setup({
63
+ :current => "{PWD}/{TOPLEVEL}/{SUBPATH}",
64
+ :user => "{HOME}/.{PKGDIR}/{TOPLEVEL}/{SUBPATH}",
65
+ :global => '/{TOPLEVEL}/{PKGDIR}/{SUBPATH}',
66
+ :usr => '/usr/{TOPLEVEL}/{PKGDIR}/{SUBPATH}',
67
+ :local => '/usr/local/{TOPLEVEL}/{PKGDIR}/{SUBPATH}',
68
+ :fast => '/fast/{TOPLEVEL}/{PKGDIR}/{SUBPATH}',
69
+ :cache => '/cache/{TOPLEVEL}/{PKGDIR}/{SUBPATH}',
70
+ :bulk => '/bulk/{TOPLEVEL}/{PKGDIR}/{SUBPATH}',
71
+ :lib => '{LIBDIR}/{TOPLEVEL}/{SUBPATH}',
72
+ :scout_gear => File.join(Path.caller_lib_dir(__FILE__), "{TOPLEVEL}/{SUBPATH}"),
73
+ :tmp => '/tmp/{PKGDIR}/{TOPLEVEL}/{SUBPATH}',
74
+ :default => :user
75
+ })
76
+ end
77
+
78
+ def self.basic_map_order
79
+ @@basic_map_order ||= %w(current workflow user local global lib fast cache bulk)
80
+ end
81
+
82
+ def self.map_order
83
+ @@map_order ||= (path_maps.keys & basic_map_order) + (path_maps.keys - basic_map_order)
84
+ end
85
+
86
+ def self.add_path(name, map)
87
+ @@path_maps[name] = map
88
+ @@map_order = nil
89
+ end
90
+
91
+ def _parts
92
+ @_parts ||= self.split("/")
93
+ end
94
+
95
+ def _subpath
96
+ @subpath ||= _parts.length > 1 ? _parts[1..-1] * "/" : _parts[0] || ""
97
+ end
98
+
99
+ def _toplevel
100
+ @toplevel ||= _parts.length > 1 ? _parts[0] : ""
101
+ end
102
+
103
+ SLASH = "/"[0]
104
+ DOT = "."[0]
105
+ def located?
106
+ # OPEN RESOURCE
107
+ self.slice(0,1) == SLASH || (self.slice(0,1) == DOT && self.slice(1,2) == SLASH) # || (resource != Rbbt && (Open.remote?(self) || Open.ssh?(self)))
108
+ end
109
+
110
+ def annotate_found_where(found, where)
111
+ self.annotate(found).tap{|p|
112
+ p.instance_variable_set("@where", where)
113
+ p.instance_variable_set("@original", self.dup)
114
+ }
115
+ end
116
+
117
+ def where
118
+ @where
119
+ end
120
+
121
+ def original
122
+ @original
123
+ end
124
+
125
+ def map_order
126
+ @map_order ||= (path_maps.keys & Path.basic_map_order) + (path_maps.keys - Path.basic_map_order)
127
+ end
128
+
129
+ def follow(map_name = :default, annotate = true)
130
+ IndiferentHash.setup(path_maps)
131
+ map = path_maps[map_name] || Path.path_maps[map_name]
132
+ if map.nil? && String === map_name
133
+ map = File.join(map_name, '{TOPLEVEL}/{SUBPATH}')
134
+ end
135
+ raise "Map not found #{Log.fingerprint map_name} not in #{Log.fingerprint path_maps.keys}" if map.nil?
136
+ while Symbol === map
137
+ map_name = map
138
+ map = path_maps[map_name]
139
+ end
140
+ found = Path.follow(self, map, map_name)
141
+
142
+ annotate_found_where(found, map_name) if annotate
143
+
144
+ found
145
+ end
146
+
147
+ def self.exists_file_or_alternatives(file)
148
+ return file if File.exist?(file) or File.directory?(file)
149
+ %w(gz bgz zip).each do |extension|
150
+ alt_file = file + '.' + extension
151
+ return alt_file if File.exist?(alt_file) or File.directory?(alt_file)
152
+ end
153
+ nil
154
+ end
155
+
156
+ def find(where = nil)
157
+ if located?
158
+ if File.exist?(self)
159
+ return self if located?
160
+ else
161
+ found = Path.exists_file_or_alternatives(self)
162
+ if found
163
+ return self.annotate(found)
164
+ else
165
+ return self if located?
166
+ end
167
+ end
168
+ end
169
+
170
+ return find_all if where == 'all' || where == :all
171
+
172
+ return follow(where) if where
173
+
174
+ map_order.each do |map_name|
175
+ found = follow(map_name, false)
176
+
177
+ found = Path.exists_file_or_alternatives(found)
178
+ return annotate_found_where(found, map_name) if found
179
+ end
180
+
181
+ return follow(:default)
182
+ end
183
+
184
+ def exist?
185
+ # OPEN
186
+ found = self.find
187
+ File.exist?(found) || File.directory?(found)
188
+ end
189
+
190
+ alias exists? exist?
191
+
192
+ def find_all(caller_lib = nil, search_paths = nil)
193
+ map_order
194
+ .collect{|where| find(where) }
195
+ .select{|file| file.exist? }.uniq
196
+ end
197
+
198
+ def find_with_extension(extension, *args)
199
+ found = self.find(*args)
200
+ return found if found.exists?
201
+ found_with_extension = self.set_extension(extension).find
202
+ found_with_extension.exists? ? found_with_extension : found
203
+ end
204
+ end
@@ -0,0 +1,8 @@
1
+ module TmpFile
2
+ def self.with_path(*args, &block)
3
+ TmpFile.with_file(*args) do |file|
4
+ Path.setup(file)
5
+ yield file
6
+ end
7
+ end
8
+ end