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.
- checksums.yaml +7 -0
- data/.document +5 -0
- data/.vimproject +78 -0
- data/Gemfile +14 -0
- data/LICENSE.txt +20 -0
- data/README.rdoc +18 -0
- data/Rakefile +47 -0
- data/VERSION +1 -0
- data/lib/scout/cmd.rb +348 -0
- data/lib/scout/concurrent_stream.rb +284 -0
- data/lib/scout/config.rb +168 -0
- data/lib/scout/exceptions.rb +77 -0
- data/lib/scout/indiferent_hash/case_insensitive.rb +30 -0
- data/lib/scout/indiferent_hash/options.rb +115 -0
- data/lib/scout/indiferent_hash.rb +96 -0
- data/lib/scout/log/color.rb +224 -0
- data/lib/scout/log/color_class.rb +269 -0
- data/lib/scout/log/fingerprint.rb +69 -0
- data/lib/scout/log/progress/report.rb +244 -0
- data/lib/scout/log/progress/util.rb +173 -0
- data/lib/scout/log/progress.rb +106 -0
- data/lib/scout/log/trap.rb +107 -0
- data/lib/scout/log.rb +441 -0
- data/lib/scout/meta_extension.rb +100 -0
- data/lib/scout/misc/digest.rb +63 -0
- data/lib/scout/misc/filesystem.rb +25 -0
- data/lib/scout/misc/format.rb +255 -0
- data/lib/scout/misc/helper.rb +31 -0
- data/lib/scout/misc/insist.rb +56 -0
- data/lib/scout/misc/monitor.rb +66 -0
- data/lib/scout/misc/system.rb +73 -0
- data/lib/scout/misc.rb +10 -0
- data/lib/scout/named_array.rb +138 -0
- data/lib/scout/open/lock/lockfile.rb +587 -0
- data/lib/scout/open/lock.rb +68 -0
- data/lib/scout/open/remote.rb +135 -0
- data/lib/scout/open/stream.rb +491 -0
- data/lib/scout/open/util.rb +244 -0
- data/lib/scout/open.rb +170 -0
- data/lib/scout/path/find.rb +204 -0
- data/lib/scout/path/tmpfile.rb +8 -0
- data/lib/scout/path/util.rb +127 -0
- data/lib/scout/path.rb +51 -0
- data/lib/scout/persist/open.rb +17 -0
- data/lib/scout/persist/path.rb +15 -0
- data/lib/scout/persist/serialize.rb +157 -0
- data/lib/scout/persist.rb +104 -0
- data/lib/scout/resource/open.rb +8 -0
- data/lib/scout/resource/path.rb +80 -0
- data/lib/scout/resource/produce/rake.rb +69 -0
- data/lib/scout/resource/produce.rb +151 -0
- data/lib/scout/resource/scout.rb +3 -0
- data/lib/scout/resource/software.rb +178 -0
- data/lib/scout/resource/util.rb +59 -0
- data/lib/scout/resource.rb +40 -0
- data/lib/scout/simple_opt/accessor.rb +54 -0
- data/lib/scout/simple_opt/doc.rb +126 -0
- data/lib/scout/simple_opt/get.rb +57 -0
- data/lib/scout/simple_opt/parse.rb +67 -0
- data/lib/scout/simple_opt/setup.rb +26 -0
- data/lib/scout/simple_opt.rb +5 -0
- data/lib/scout/tmpfile.rb +129 -0
- data/lib/scout-essentials.rb +10 -0
- data/scout-essentials.gemspec +143 -0
- data/share/color/color_names +507 -0
- data/share/color/diverging_colors.hex +12 -0
- data/share/software/install_helpers +523 -0
- data/test/scout/indiferent_hash/test_case_insensitive.rb +16 -0
- data/test/scout/indiferent_hash/test_options.rb +46 -0
- data/test/scout/log/test_color.rb +0 -0
- data/test/scout/log/test_progress.rb +108 -0
- data/test/scout/misc/test_digest.rb +30 -0
- data/test/scout/misc/test_filesystem.rb +30 -0
- data/test/scout/misc/test_insist.rb +13 -0
- data/test/scout/misc/test_system.rb +21 -0
- data/test/scout/open/test_lock.rb +52 -0
- data/test/scout/open/test_remote.rb +25 -0
- data/test/scout/open/test_stream.rb +676 -0
- data/test/scout/open/test_util.rb +73 -0
- data/test/scout/path/test_find.rb +110 -0
- data/test/scout/path/test_util.rb +22 -0
- data/test/scout/persist/test_open.rb +37 -0
- data/test/scout/persist/test_path.rb +37 -0
- data/test/scout/persist/test_serialize.rb +114 -0
- data/test/scout/resource/test_path.rb +58 -0
- data/test/scout/resource/test_produce.rb +94 -0
- data/test/scout/resource/test_software.rb +24 -0
- data/test/scout/resource/test_util.rb +38 -0
- data/test/scout/simple_opt/test_doc.rb +16 -0
- data/test/scout/simple_opt/test_get.rb +11 -0
- data/test/scout/simple_opt/test_parse.rb +10 -0
- data/test/scout/simple_opt/test_setup.rb +77 -0
- data/test/scout/test_cmd.rb +85 -0
- data/test/scout/test_concurrent_stream.rb +29 -0
- data/test/scout/test_config.rb +66 -0
- data/test/scout/test_indiferent_hash.rb +26 -0
- data/test/scout/test_log.rb +32 -0
- data/test/scout/test_meta_extension.rb +80 -0
- data/test/scout/test_misc.rb +6 -0
- data/test/scout/test_named_array.rb +43 -0
- data/test/scout/test_open.rb +146 -0
- data/test/scout/test_path.rb +54 -0
- data/test/scout/test_persist.rb +186 -0
- data/test/scout/test_resource.rb +26 -0
- data/test/scout/test_tmpfile.rb +53 -0
- data/test/test_helper.rb +50 -0
- 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
|