scout-essentials 1.7.1 → 1.8.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 (54) hide show
  1. checksums.yaml +4 -4
  2. data/.vimproject +200 -47
  3. data/README.md +136 -0
  4. data/Rakefile +1 -0
  5. data/VERSION +1 -1
  6. data/doc/Annotation.md +352 -0
  7. data/doc/CMD.md +203 -0
  8. data/doc/ConcurrentStream.md +163 -0
  9. data/doc/IndiferentHash.md +240 -0
  10. data/doc/Log.md +235 -0
  11. data/doc/NamedArray.md +174 -0
  12. data/doc/Open.md +331 -0
  13. data/doc/Path.md +217 -0
  14. data/doc/Persist.md +214 -0
  15. data/doc/Resource.md +229 -0
  16. data/doc/SimpleOPT.md +236 -0
  17. data/doc/TmpFile.md +154 -0
  18. data/lib/scout/annotation/annotated_object.rb +8 -0
  19. data/lib/scout/annotation/annotation_module.rb +1 -0
  20. data/lib/scout/cmd.rb +19 -12
  21. data/lib/scout/concurrent_stream.rb +3 -1
  22. data/lib/scout/config.rb +2 -2
  23. data/lib/scout/indiferent_hash/options.rb +2 -2
  24. data/lib/scout/indiferent_hash.rb +16 -0
  25. data/lib/scout/log/color.rb +5 -3
  26. data/lib/scout/log/fingerprint.rb +8 -8
  27. data/lib/scout/log/progress/report.rb +6 -6
  28. data/lib/scout/log.rb +7 -7
  29. data/lib/scout/misc/digest.rb +11 -13
  30. data/lib/scout/misc/format.rb +2 -2
  31. data/lib/scout/misc/system.rb +5 -0
  32. data/lib/scout/open/final.rb +16 -1
  33. data/lib/scout/open/remote.rb +0 -1
  34. data/lib/scout/open/stream.rb +30 -5
  35. data/lib/scout/open/util.rb +32 -0
  36. data/lib/scout/path/digest.rb +12 -2
  37. data/lib/scout/path/find.rb +19 -6
  38. data/lib/scout/path/util.rb +37 -1
  39. data/lib/scout/persist/open.rb +2 -0
  40. data/lib/scout/persist.rb +7 -1
  41. data/lib/scout/resource/path.rb +2 -2
  42. data/lib/scout/resource/util.rb +18 -4
  43. data/lib/scout/resource.rb +15 -1
  44. data/lib/scout/simple_opt/parse.rb +2 -0
  45. data/lib/scout/tmpfile.rb +1 -1
  46. data/scout-essentials.gemspec +19 -6
  47. data/test/scout/misc/test_hook.rb +2 -2
  48. data/test/scout/open/test_stream.rb +43 -15
  49. data/test/scout/path/test_find.rb +1 -1
  50. data/test/scout/path/test_util.rb +11 -0
  51. data/test/scout/test_path.rb +4 -4
  52. data/test/scout/test_persist.rb +10 -1
  53. metadata +31 -5
  54. data/README.rdoc +0 -18
@@ -120,18 +120,18 @@ module Log
120
120
  str = Log.color(:magenta, "·")
121
121
  if @ticks == 0
122
122
  if @max
123
- return str << " " << Log.color(:magenta, "waiting on #{@max} #{bytes ? 'bytes' : 'items'}") << Log.color(:magenta, " · " << desc)
123
+ return str + " " << Log.color(:magenta, "waiting on #{@max} #{bytes ? 'bytes' : 'items'}") << Log.color(:magenta, " · " + desc)
124
124
  else
125
- return str << " " << Log.color(:magenta, "waiting - PID: #{Process.pid}") << Log.color(:magenta, " · " << desc)
125
+ return str + " " << Log.color(:magenta, "waiting - PID: #{Process.pid}") << Log.color(:magenta, " · " + desc)
126
126
  end
127
127
  end
128
- str << " " << thr_msg
128
+ str += " " + thr_msg
129
129
  if max
130
130
  str << Log.color(:blue, " -- ") << eta_msg
131
131
  else
132
132
  str << Log.color(:blue, " -- ") << ticks.to_s << " #{bytes ? 'bytes' : 'items'}"
133
133
  end
134
- str << Log.color(:magenta, " · " << desc)
134
+ str << Log.color(:magenta, " · " + desc)
135
135
  str
136
136
  end
137
137
 
@@ -208,8 +208,8 @@ module Log
208
208
  @last_count = 0
209
209
  @last_time = @start
210
210
  thr = ellapsed > 0 ? (@ticks / ellapsed).to_i.to_s : 0
211
- done_msg << " - " << Log.color(:blue, thr) << " per second"
212
- done_msg << Log.color(:magenta, " · " << desc)
211
+ done_msg << " - " + Log.color(:blue, thr) << " per second"
212
+ done_msg << Log.color(:magenta, " · " + desc)
213
213
  print(io, Log.up_lines(@depth) << done_msg << Log.down_lines(@depth))
214
214
 
215
215
  FileUtils.rm file if file and File.exist?(file)
data/lib/scout/log.rb CHANGED
@@ -59,7 +59,7 @@ module Log
59
59
  IO.console.winsize.last
60
60
  rescue Exception
61
61
  begin
62
- res = `tput li`
62
+ res = `tput cols`
63
63
  res = nil if res == ""
64
64
  res || ENV["TTY_SIZE"] || 80
65
65
  rescue Exception
@@ -165,7 +165,7 @@ module Log
165
165
  end
166
166
  end
167
167
 
168
- LAST = "log"
168
+ LAST = "log".dup
169
169
  def self.logn(message = nil, severity = MEDIUM, &block)
170
170
  return if severity < self.severity
171
171
  message ||= block.call if block_given?
@@ -180,8 +180,8 @@ module Log
180
180
  else
181
181
  prefix = time << color(severity) << "[" << sev_str << "]" << color(0)
182
182
  end
183
- message = "" << highlight << message << color(0) if severity >= INFO
184
- str = prefix << " " << message.to_s
183
+ message = [highlight, message, color(0)].join if severity >= INFO
184
+ str = prefix + " " + message.to_s
185
185
 
186
186
  log_write str
187
187
 
@@ -288,9 +288,9 @@ module Log
288
288
  end
289
289
 
290
290
  def self.tsv(tsv, example = false)
291
- log_puts Log.color :magenta, "TSV log: " << Log.last_caller(caller).gsub('`',"'")
292
- log_puts Log.color(:blue, "=> "<< Log.fingerprint(tsv), true)
293
- log_puts Log.color(:cyan, "=> " << tsv.summary)
291
+ log_puts Log.color :magenta, "TSV log: " + Log.last_caller(caller).gsub('`',"'")
292
+ log_puts Log.color(:blue, "=> " + Log.fingerprint(tsv), true)
293
+ log_puts Log.color(:cyan, "=> " + tsv.summary)
294
294
  if example && ! tsv.empty?
295
295
  key = case example
296
296
  when TrueClass, :first, "first"
@@ -8,15 +8,7 @@ module Misc
8
8
  case obj
9
9
  when String
10
10
  if Path.is_filename?(obj) && Open.exists?(obj)
11
- if File.directory?(obj)
12
- if Path === obj
13
- "Directory MD5: #{digest_str(obj.glob("*"))}"
14
- else
15
- "Directory MD5: #{digest_str(Dir.glob(File.join(obj, "*")))}"
16
- end
17
- else
18
- "File MD5: #{Misc.digest_file(obj)}"
19
- end
11
+ Path.setup(obj).digest_str
20
12
  else
21
13
  obj.dup
22
14
  end
@@ -27,12 +19,12 @@ module Misc
27
19
  length = obj.length
28
20
  mid = length/2
29
21
  sample_pos = [1, 2, mid, length-2, length-1]
30
- "[#{length}:" << obj.values_at(*sample_pos).inject(""){|acc,o| acc.empty? ? Misc.digest_str(o) : acc << ', ' << Misc.digest_str(o) } << ']'
22
+ "[#{length}:" + obj.values_at(*sample_pos).inject(""){|acc,o| acc.empty? ? Misc.digest_str(o) : acc << ', ' << Misc.digest_str(o) } << ']'
31
23
  else
32
- '[' << obj.inject(""){|acc,o| acc.empty? ? Misc.digest_str(o) : acc << ', ' << Misc.digest_str(o) } << ']'
24
+ '[' + obj.inject("".dup){|acc,o| acc.empty? ? Misc.digest_str(o) : acc << ', ' << Misc.digest_str(o) } << ']'
33
25
  end
34
26
  when Hash
35
- '{' << obj.inject(""){|acc,p| s = Misc.digest_str(p.first) << "=" << Misc.digest_str(p.last); acc.empty? ? s : acc << ', ' << s } << '}'
27
+ '{' + obj.inject(""){|acc,p| s = Misc.digest_str(p.first) + "=" << Misc.digest_str(p.last); acc.empty? ? s : acc << ', ' << s } << '}'
36
28
  when Integer
37
29
  obj.to_s
38
30
  when Float
@@ -49,6 +41,8 @@ module Misc
49
41
  "true"
50
42
  when FalseClass
51
43
  "false"
44
+ when Proc
45
+ Misc.digest obj.source_location
52
46
  else
53
47
  obj.inspect
54
48
  end
@@ -63,7 +57,11 @@ module Misc
63
57
  def self.file_md5(file)
64
58
  file = file.find if Path === file
65
59
  file = File.expand_path(file)
66
- Digest::MD5.file(file).hexdigest
60
+ begin
61
+ Digest::MD5.file(file).hexdigest
62
+ rescue
63
+ Digest::MD5.hexdigest(file)
64
+ end
67
65
  end
68
66
 
69
67
  def self.fast_file_md5(file, sample = 3_000_000)
@@ -44,7 +44,7 @@ module Misc
44
44
  offset ||= 0
45
45
 
46
46
  i = 0
47
- size = size + offset + indent
47
+ #size = size + offset + indent
48
48
  re = /((?:\n\s*\n\s*)|(?:\n\s*(?=\*)))/
49
49
  text.split(re).collect do |paragraph|
50
50
  i += 1
@@ -74,7 +74,7 @@ module Misc
74
74
 
75
75
  def self.format_definition_list_item(dt, dd, indent = nil, size = nil, color: :yellow)
76
76
  if size.nil?
77
- base_size = MAX_TTY_LINE_WIDTH
77
+ base_size = Log.tty_size || MAX_TTY_LINE_WIDTH
78
78
  base_indent = indent || (base_size / 3)
79
79
  size = base_size - base_indent
80
80
  end
@@ -1,5 +1,10 @@
1
1
  module Misc
2
2
 
3
+ def self.add_libdir(dir=nil)
4
+ dir ||= File.join(Path.caller_lib_dir(caller.first), 'lib')
5
+ $LOAD_PATH.unshift(dir) unless $LOAD_PATH.include? dir
6
+ end
7
+
3
8
  def self.hostname
4
9
  @@hostname ||= begin
5
10
  (ENV["HOSTNAME"] || `hostname`).strip
@@ -70,6 +70,12 @@ module Open
70
70
  notify_write(file)
71
71
  end
72
72
 
73
+ def append(file, content, options = {})
74
+ options = IndiferentHash.setup options
75
+ options[:mode] = "a"
76
+ write(file, content, options)
77
+ end
78
+
73
79
  def self.mv(source, target, options = {})
74
80
  target = target.find if Path === target
75
81
  source = source.find if Path === source
@@ -81,6 +87,7 @@ module Open
81
87
  end
82
88
 
83
89
  def self.rm(file)
90
+ file = file.find if Path === file
84
91
  FileUtils.rm(file) if File.exist?(file) || Open.broken_link?(file)
85
92
  end
86
93
 
@@ -101,6 +108,14 @@ module Open
101
108
  end
102
109
  end
103
110
 
111
+ def self.mkfiledir(target)
112
+ target = target.find if Path === target
113
+ dir = File.dirname(target)
114
+ if ! File.exist?(dir)
115
+ FileUtils.mkdir_p dir
116
+ end
117
+ end
118
+
104
119
  def self.cp(source, target, options = {})
105
120
  source = source.find if Path === source
106
121
  target = target.find if Path === target
@@ -188,7 +203,7 @@ module Open
188
203
  begin
189
204
  Open.ln(source, target, options)
190
205
  rescue
191
- Log.debug "Could not make regular link, trying symbolic: #{Misc.fingerprint(source)} -> #{Misc.fingerprint(target)}"
206
+ Log.debug "Could not make regular link, trying symbolic: #{Log.fingerprint(source)} -> #{Log.fingerprint(target)}"
192
207
  Open.ln_s(source, target, options)
193
208
  end
194
209
  nil
@@ -92,7 +92,6 @@ module Open
92
92
  open_cache(url, options)
93
93
  end
94
94
  rescue
95
- STDERR.puts $!.backtrace.inspect
96
95
  raise OpenURLError, "Error reading remote url: #{ url }.\n#{$!.message}"
97
96
  end
98
97
  end
@@ -204,6 +204,7 @@ module Open
204
204
 
205
205
  def self.purge_pipes(*save)
206
206
  PIPE_MUTEX.synchronize do
207
+ save = save.flatten
207
208
  OPEN_PIPE_IN.each do |pipe|
208
209
  next if save.include? pipe
209
210
  pipe.close unless pipe.closed?
@@ -361,7 +362,7 @@ module Open
361
362
  end
362
363
 
363
364
  main_pipe.abort_callback = proc do |exception|
364
- stream.abort(exception)
365
+ stream.abort(exception) if ConcurrentStream === stream
365
366
  out_pipes[1..-1].each do |sout|
366
367
  sout.abort(exception)
367
368
  end
@@ -398,10 +399,11 @@ module Open
398
399
  end
399
400
 
400
401
  def self.read_stream(stream, size)
401
- str = ""
402
+ str = "".dup
402
403
  while str.length < size
403
404
  missing = size - str.length
404
405
  more = stream.read(missing)
406
+ raise ClosedStream if more.nil?
405
407
  str << more
406
408
  end
407
409
  str
@@ -464,15 +466,15 @@ module Open
464
466
  if compact
465
467
  current_parts[i] = part.dup
466
468
  else
467
- current_parts[i] = "|" << part
469
+ current_parts[i] = "|" + part
468
470
  end
469
471
  else
470
- current_parts[i] = current_parts[i] << "|" << part
472
+ current_parts[i] = current_parts[i] + "|" << part
471
473
  end
472
474
  end
473
475
 
474
476
  (parts.length..current_parts.length-1).to_a.each do |pos|
475
- current_parts[pos] = current_parts[pos] << "|" << ""
477
+ current_parts[pos] = current_parts[pos] + "|" << ""
476
478
  end
477
479
  when current_key.nil?
478
480
  current_key = key
@@ -498,4 +500,27 @@ module Open
498
500
  end unless current_key.nil?
499
501
  end
500
502
  end
503
+
504
+ def self.line_monitor_stream(stream, &block)
505
+ monitor, out = tee_stream stream
506
+ monitor_thread = Thread.new do
507
+ begin
508
+ while line = monitor.gets
509
+ block.call line
510
+ end
511
+ rescue
512
+ monitor.abort $!
513
+ monitor.close unless monitor.closed?
514
+ monitor.join if monitor.respond_to?(:join) && ! monitor.aborted?
515
+ out.raise $! if out.respond_to?(:raise)
516
+ ensure
517
+ monitor.close unless monitor.closed?
518
+ monitor.join if monitor.respond_to?(:join) && ! monitor.aborted?
519
+ end
520
+ end
521
+ monitor_thread.report_on_exception = false
522
+
523
+ stream.annotate out if stream.respond_to? :annotate
524
+ ConcurrentStream.setup out, :threads => monitor_thread
525
+ end
501
526
  end
@@ -1,3 +1,4 @@
1
+ require 'pathname'
1
2
  module Open
2
3
  GREP_CMD = begin
3
4
  if ENV["GREP_CMD"]
@@ -129,4 +130,35 @@ module Open
129
130
  file = file.produce_and_find if Path === file
130
131
  Open.read(file).split("\n")
131
132
  end
133
+
134
+ def self.wait_for(path, timeout: 10)
135
+ return if Open.exists?(path)
136
+
137
+ path = path.find if Path === path
138
+
139
+ require 'listen'
140
+ require 'timeout'
141
+
142
+ dir = File.dirname(path)
143
+ name = File.basename(path)
144
+
145
+ queue = Queue.new
146
+ listener = Listen.to(dir) do |_modified, added, _removed|
147
+ queue << :found if added.include?(path)
148
+ end
149
+
150
+ listener.start
151
+
152
+ begin
153
+ Timeout.timeout(timeout) do
154
+ # This blocks until something is pushed to the queue
155
+ queue.pop
156
+ end
157
+ true
158
+ rescue Timeout::Error
159
+ false
160
+ ensure
161
+ listener.stop
162
+ end
163
+ end
132
164
  end
@@ -3,11 +3,21 @@ module Path
3
3
  def digest_str
4
4
  case
5
5
  when File.directory?(self)
6
- "Directory MD5: #{Misc.digest_str(self.glob("*"))}"
6
+ files = self.glob("*")
7
+
8
+ files = files.reject{|f| File.directory?(f) }
9
+
10
+ files = Annotation.purge files
11
+
12
+ if files.length > 10
13
+ "Directory MD5: #{files.length} #{Misc.digest_str(files*"\n")}"
14
+ else
15
+ "Directory MD5: #{Misc.digest_str(files)}"
16
+ end
7
17
  when self.located? && File.exist?(self)
8
18
  "File MD5: #{Misc.digest_file(self)}"
9
19
  else
10
- '\'' << self << '\''
20
+ '\'' + self << '\''
11
21
  end
12
22
  end
13
23
  end
@@ -6,12 +6,15 @@ module Path
6
6
  caller_dup = caller.dup
7
7
  while file = caller_dup.shift
8
8
  break unless file =~ /(?:scout|rbbt)\/(?:resource\.rb|workflow\.rb)/ or
9
- file =~ /(?:scout|rbbt)\/(?:.*\/)?(path|open|final|tsv|refactor)\.rb/ or
9
+ file =~ /(?:scout|rbbt)\/(?:.*\/)?(path|open|final|tsv|refactor|hook|parser)\.rb/ or
10
10
  file =~ /(?:scout|rbbt)\/(?:.*\/)?path\/(?:find|refactor|util)\.rb/ or
11
11
  file =~ /(?:scout|rbbt)\/persist.rb/ or
12
+ file =~ /(?:scout|rbbt)\/(persist|workflow)\// or
12
13
  file =~ /scout\/resource\/produce.rb/ or
13
- file =~ /modules\/rbbt-util/
14
+ file =~ /modules\/rbbt-util/ or
15
+ file =~ /^<internal:/
14
16
  end
17
+
15
18
  return nil if file.nil?
16
19
  file = file.sub(/\.rb[^\w].*/,'.rb')
17
20
  end
@@ -65,6 +68,8 @@ module Path
65
68
  sub('{REMOVE}/', '').
66
69
  sub('{REMOVE}', '')
67
70
 
71
+ file.sub!(/\/$/,'') if path._subpath.nil?
72
+
68
73
  while true
69
74
  file.gsub!(/\{(.+)(?<!\\)\/(.+)(?<!\\)\/(.+)\}/) do |m|
70
75
  key, orig, replace = m.split(/(?<!\\)\//).collect{|p| p.gsub('\/','/') }
@@ -281,10 +286,18 @@ module Path
281
286
  .select{|file| file.exist? }.uniq
282
287
  end
283
288
 
284
- def find_with_extension(extension, *args)
289
+ def find_with_extension(extension, *args, produce: true)
285
290
  found = self.find(*args)
286
- return found if found.exists?
287
- found_with_extension = self.set_extension(extension).find
288
- found_with_extension.exists? ? found_with_extension : found
291
+ return found if found.exists?(produce: produce) && ! found.directory?
292
+ if Array === extension
293
+ extension.each do |ext|
294
+ found_with_extension = self.set_extension(ext).find
295
+ return found_with_extension if found_with_extension.exists?(produce: produce)
296
+ end
297
+ else
298
+ found_with_extension = self.set_extension(extension).find
299
+ return found_with_extension if found_with_extension.exists?(produce: produce)
300
+ end
301
+ return found
289
302
  end
290
303
  end
@@ -15,6 +15,14 @@ module Path
15
15
  return false
16
16
  end
17
17
 
18
+ def self.can_read?(string)
19
+ return true if Open.remote?(string)
20
+ return false unless Path.is_filename?(string)
21
+ string = string.find if Path === string
22
+ return false if File.directory?(string)
23
+ return true
24
+ end
25
+
18
26
  def self.sanitize_filename(filename, length = 254)
19
27
  if filename.length > length
20
28
  if filename =~ /(\..{2,9})$/
@@ -37,6 +45,14 @@ module Path
37
45
  File.directory?(self.find)
38
46
  end
39
47
 
48
+ def realpath
49
+ File.realpath(self.find)
50
+ end
51
+
52
+ def relative_to(dir)
53
+ Misc.path_relative_to(File.expand_path(dir), self.find)
54
+ end
55
+
40
56
  def sub(*args)
41
57
  self.annotate super(*args)
42
58
  end
@@ -71,12 +87,17 @@ module Path
71
87
  end
72
88
  end
73
89
 
90
+ def glob_names(...)
91
+ glob(...).collect{|f| f.basename }
92
+ end
93
+
74
94
  def glob_all(pattern = nil, caller_lib = nil, search_paths = nil)
75
95
  search_paths ||= self.path_maps || Path.path_maps
76
96
  search_paths = search_paths.dup
77
97
 
78
98
  search_paths.keys.collect do |where|
79
99
  found = find(where)
100
+ next unless found.located?
80
101
 
81
102
  paths = pattern ? found.glob(pattern) : found.glob
82
103
 
@@ -135,8 +156,17 @@ module Path
135
156
  self.annotate(new_path)
136
157
  end
137
158
 
159
+ def newer_files(*files)
160
+ files.flatten.select do |file|
161
+ Path.newer?(self, file)
162
+ end
163
+ end
138
164
 
139
- # Is 'file' newer than 'path'? return non-true if path is newer than file
165
+ def outdated?(...)
166
+ newer_files(...).any?
167
+ end
168
+
169
+ # Is 'file' newer than 'path'? return false if path is newer than file
140
170
  def self.newer?(path, file, by_link = false)
141
171
  return true if not Open.exists?(file)
142
172
  path = path.find if Path === path
@@ -153,4 +183,10 @@ module Path
153
183
  return diff if diff < 0
154
184
  return false
155
185
  end
186
+
187
+ def final_pkgdir
188
+ final_pkgdir = self.pkgdir
189
+ final_pkgdir = final_pkgdir.pkgdir while final_pkgdir.respond_to?(:pkgdir)
190
+ final_pkgdir
191
+ end
156
192
  end
@@ -4,10 +4,12 @@ require 'yaml'
4
4
 
5
5
  module Open
6
6
  def self.json(file)
7
+ file = file.find_with_extension :json if Path === file
7
8
  Open.open(file){|f| JSON.load(f) }
8
9
  end
9
10
 
10
11
  def self.yaml(file)
12
+ file = file.find_with_extension :yaml if Path === file
11
13
  Open.open(file){|f| YAML.unsafe_load(f) }
12
14
  end
13
15
 
data/lib/scout/persist.rb CHANGED
@@ -8,6 +8,7 @@ module Persist
8
8
  def cache_dir=(cache_dir)
9
9
  @cache_dir = Path === cache_dir ? cache_dir : Path.setup(cache_dir)
10
10
  end
11
+
11
12
  def cache_dir
12
13
  @cache_dir ||= Path.setup("var/cache/persistence")
13
14
  end
@@ -34,11 +35,16 @@ module Persist
34
35
 
35
36
  file = persist_options[:path] || options[:path] || persistence_path(name, options)
36
37
  data = persist_options[:data] || options[:data]
38
+ check = persist_options[:check] || options[:check]
37
39
  no_load = persist_options[:no_load] || options[:no_load]
38
40
 
39
41
  update = options[:update] || persist_options[:update]
40
42
  update = Open.mtime(update) if Path === update
41
- update = Open.mtime(file) >= update ? false : true if Time === update
43
+
44
+ update = true if file.outdated?(check) if Path === file && check
45
+ file_mtime = Open.mtime(file)
46
+ update = file_mtime >= update ? false : true if file_mtime && Time === update
47
+ update = file_mtime >= (Time.now - update) ? false : true if file_mtime && Numeric === update
42
48
 
43
49
  if type == :memory
44
50
  repo = options[:memory] || options[:repo] || MEMORY_CACHE
@@ -74,8 +74,8 @@ module Path
74
74
  Open.list(found)
75
75
  end
76
76
 
77
- def exists?
77
+ def exists?(produce: true)
78
78
  return true if Open.exists?(self.find)
79
- self.produce
79
+ self.produce if produce
80
80
  end
81
81
  end
@@ -15,6 +15,8 @@ module Resource
15
15
  path = File.expand_path(path) if path.start_with?('/')
16
16
  path += "/" if File.directory?(path) and not path.end_with?('/')
17
17
 
18
+ self_pkgdir = self.final_pkgdir
19
+
18
20
  choices = []
19
21
  map_order.uniq.each do |name|
20
22
  pattern = path_maps[name]
@@ -31,7 +33,7 @@ module Resource
31
33
  .gsub(/\/{([^}]+)}/,'(?:/(?<\1>[^/]+))?') +
32
34
  "(?:/(?<REST>.+))?/?$"
33
35
  if m = path.match(regexp)
34
- if ! m.named_captures.include?("PKGDIR") || m["PKGDIR"] == self.pkgdir
36
+ if ! m.named_captures.include?("PKGDIR") || m["PKGDIR"] == self_pkgdir
35
37
 
36
38
  unlocated = %w(TOPLEVEL SUBPATH PATH REST).collect{|c|
37
39
  m.named_captures.include?(c) ? m[c] : nil
@@ -40,10 +42,11 @@ module Resource
40
42
  if self.subdir && ! self.subdir.empty?
41
43
  subdir = self.subdir
42
44
  subdir += "/" unless subdir.end_with?("/")
43
- unlocated[subdir] = ""
45
+ unlocated[subdir] = ""
44
46
  end
45
47
 
46
- choices << self.annotate(unlocated)
48
+ unlocated = path.annotate(unlocated) if Path === path
49
+ choices << unlocated
47
50
  end
48
51
  end
49
52
  end
@@ -51,13 +54,24 @@ module Resource
51
54
 
52
55
  identified = choices.sort_by{|s| s.length }.first
53
56
 
54
- Path.setup(identified || path, self, nil, path_maps)
57
+ identified ||= path
58
+
59
+ home = ENV['HOME']
60
+ if home
61
+ home += home[0..-2] if home.end_with?('/')
62
+ identified = identified.sub(/^#{home}(\/|$)/, '~\1')
63
+ end
64
+
65
+ Path.setup(identified, self, nil, path_maps) unless Path === identified
66
+
67
+ identified
55
68
  end
56
69
 
57
70
  def self.identify(path)
58
71
  resource = path.pkgdir if Path === path
59
72
  resource = Resource.default_resource unless Resource === resource
60
73
  unlocated = resource.identify path
74
+ unlocated
61
75
  end
62
76
 
63
77
  def self.relocate(path)
@@ -33,7 +33,21 @@ module Resource
33
33
  end
34
34
 
35
35
  def path_maps
36
- @path_maps ||= Path.path_maps
36
+ @path_maps ||= Path.path_maps.dup
37
+ end
38
+
39
+ def map_order
40
+ @map_order ||= Path.map_order.dup
41
+ end
42
+
43
+ def prepend_path(name, map)
44
+ path_maps[name] = map
45
+ map_order.unshift(name.to_sym)
46
+ end
47
+
48
+ def append_path(name, map)
49
+ path_maps[name] = map
50
+ map_order.push(name.to_sym)
37
51
  end
38
52
 
39
53
  def subdir
@@ -35,6 +35,8 @@ module SOPT
35
35
  end
36
36
 
37
37
  def self.register(short, long, asterisk, description)
38
+ long = long.to_s if Symbol === long
39
+ short = short.to_s if Symbol === short
38
40
  short = fix_shortcut(short, long)
39
41
  shortcuts[short] = long if short
40
42
  inputs << long
data/lib/scout/tmpfile.rb CHANGED
@@ -124,7 +124,7 @@ module TmpFile
124
124
 
125
125
  filename = filename[0..MAX_FILE_LENGTH] << Misc.digest(filename[MAX_FILE_LENGTH+1..-1]) if filename.length > MAX_FILE_LENGTH + 10
126
126
 
127
- filename += ":" << Misc.digest(clean_options) unless clean_options.empty?
127
+ filename += ":" + Misc.digest(clean_options) unless clean_options.empty?
128
128
 
129
129
  persistence_dir[filename]
130
130
  end