scout-essentials 1.0.0

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