Module: Path

Extended by:
Annotation
Defined in:
lib/scout/path.rb,
lib/scout/path/find.rb,
lib/scout/path/util.rb,
lib/scout/path/digest.rb,
lib/scout/persist/path.rb,
lib/scout/resource/path.rb

Constant Summary collapse

SLASH =
DOT =

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Annotation

extended, is_annotated?, purge, setup

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(name, prev = nil, *args, &block) ⇒ Object



50
51
52
53
54
55
56
# File 'lib/scout/path.rb', line 50

def method_missing(name, prev = nil, *args, &block)
  if block_given? || name.to_s.start_with?('to_')
    super name, prev, *args, &block
  else
    join(name, prev)
  end
end

Class Method Details

.add_path(name, map) ⇒ Object



92
93
94
95
# File 'lib/scout/path/find.rb', line 92

def self.add_path(name, map)
  path_maps[name] = map
  @@map_order = nil
end

.append_path(name, map) ⇒ Object



102
103
104
105
# File 'lib/scout/path/find.rb', line 102

def self.append_path(name, map)
  path_maps[name] = map
  map_order.push(name.to_sym)
end

.basic_map_orderObject



84
85
86
# File 'lib/scout/path/find.rb', line 84

def self.basic_map_order
  @@basic_map_order ||= %w(current workflow user local global lib fast cache bulk)
end

.caller_lib_dir(file = nil, relative_to = ['lib', 'bin']) ⇒ Object



4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
# File 'lib/scout/path/find.rb', line 4

def self.caller_lib_dir(file = nil, relative_to = ['lib', 'bin'])

  if file.nil?
    caller_dup = caller.dup
    while file = caller_dup.shift
      break unless file =~ /(?:scout|rbbt)\/(?:resource\.rb|workflow\.rb)/ or
        file =~ /(?:scout|rbbt)\/(?:.*\/)?(path|open|tsv|refactor)\.rb/ or
        file =~ /(?:scout|rbbt)\/(?:.*\/)?path\/(?:find|refactor|util)\.rb/ or
        file =~ /(?:scout|rbbt)\/persist.rb/ or
        file =~ /scout\/resource\/produce.rb/ or
        file =~ /modules\/rbbt-util/
    end
    return nil if file.nil?
    file = file.sub(/\.rb[^\w].*/,'.rb')
  end

  relative_to = [relative_to] unless Array === relative_to
  file = File.expand_path(file)
  return Path.setup(file) if relative_to.select{|d| File.exist? File.join(file, d)}.any?

  while file != '/'
    dir = File.dirname file

    return dir if relative_to.select{|d| File.exist? File.join(dir, d)}.any?

    file = File.dirname file
  end

  return nil
end

.default_pkgdirObject



11
12
13
# File 'lib/scout/path.rb', line 11

def self.default_pkgdir
  @@default_pkgdir ||= 'scout'
end

.default_pkgdir=(pkgdir) ⇒ Object



15
16
17
# File 'lib/scout/path.rb', line 15

def self.default_pkgdir=(pkgdir)
  @@default_pkgdir = pkgdir
end

.exists_file_or_alternatives(file) ⇒ Object



182
183
184
185
186
187
188
189
# File 'lib/scout/path/find.rb', line 182

def self.exists_file_or_alternatives(file)
  return file if File.exist?(file) or File.directory?(file)
  %w(gz bgz zip).each do |extension|
    alt_file = file + '.' + extension
    return alt_file if File.exist?(alt_file) or File.directory?(alt_file)
  end
  nil
end

.follow(path, map, map_name = nil) ⇒ Object



35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
# File 'lib/scout/path/find.rb', line 35

def self.follow(path, map, map_name = nil)
  map = File.join(map, '{PATH}') unless map.include?("{")
  if path.respond_to?(:pkgdir)
    pkgdir = path.pkgdir
    pkgdir = pkgdir.pkgdir while pkgdir.respond_to?(:pkgdir)
  end
  pkgdir = Path.default_pkgdir if pkgdir.nil?
  file = map.sub('{PKGDIR}', pkgdir).
    sub('{HOME}', ENV["HOME"]).
    sub('{RESOURCE}', path.pkgdir.to_s).
    sub('{PWD}', FileUtils.pwd).
    sub('{TOPLEVEL}', path._toplevel).
    sub('{SUBPATH}', path._subpath).
    sub('{BASENAME}', File.basename(path)).
    sub('{PATH}', path).
    sub('{LIBDIR}'){ path.libdir || (path.pkgdir.respond_to?(:libdir) && path.pkgdir.libdir) || Path.caller_lib_dir || "NOLIBDIR" }.
    sub('{MAPNAME}', map_name.to_s).
    sub('{REMOVE}/', '').
    sub('{REMOVE}', '').gsub(/\/+/,'/')

  while true
    file.gsub!(/\{(.+)(?<!\\)\/(.+)(?<!\\)\/(.+)\}/) do |m|
      key, orig, replace = m.split(/(?<!\\)\//).collect{|p| p.gsub('\/','/') }
      key_text = follow(path, "#{key}}", map_name)
      key_text[orig] = replace[0..-2] if key_text.include?(orig)
      key_text
    end || break
  end

  file
end

.is_filename?(string, need_to_exists = true) ⇒ Boolean

Returns:

  • (Boolean)


8
9
10
11
12
13
# File 'lib/scout/path/util.rb', line 8

def self.is_filename?(string, need_to_exists = true)
  return false if string.nil?
  return true if Path === string
  return true if String === string and ! string.include?("\n") and string.split("/").select{|p| p.length > 265 }.empty? and (! need_to_exists || File.exist?(string))
  return false
end

.load_path_maps(filename) ⇒ Object



117
118
119
120
121
122
123
124
125
126
127
128
# File 'lib/scout/path/find.rb', line 117

def self.load_path_maps(filename)
  Path.setup(filename) unless Path === filename
  if filename.exist?
    begin
      YAML.load(filename.read).each do |where, location|
        @@path_maps[where.to_sym] = location
      end
    rescue
      Log.error "Error loading search_paths from #{filename}: " << $!.message
    end
  end
end

.map_orderObject



88
89
90
# File 'lib/scout/path/find.rb', line 88

def self.map_order
  @@map_order ||= (path_maps.keys & basic_map_order) + (path_maps.keys - basic_map_order)
end

.newer?(path, file, by_link = false) ⇒ Boolean

Is ‘file’ newer than ‘path’? return non-true if path is newer than file

Returns:

  • (Boolean)


115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
# File 'lib/scout/path/util.rb', line 115

def self.newer?(path, file, by_link = false)
  return true if not Open.exists?(file)
  path = path.find if Path === path
  file = file.find if Path === file
  if by_link
    patht = File.exist?(path) ? File.lstat(path).mtime : nil
    filet = File.exist?(file) ? File.lstat(file).mtime : nil
  else
    patht = Open.mtime(path)
    filet = Open.mtime(file)
  end
  return true if patht.nil? || filet.nil?
  diff = patht - filet
  return diff if diff < 0
  return false
end

.path_mapsObject



67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
# File 'lib/scout/path/find.rb', line 67

def self.path_maps
  @@path_maps ||= IndiferentHash.setup({
    :current => "{PWD}/{TOPLEVEL}/{SUBPATH}",
    :user    => "{HOME}/.{PKGDIR}/{TOPLEVEL}/{SUBPATH}",
    :global  => '/{TOPLEVEL}/{PKGDIR}/{SUBPATH}',
    :usr     => '/usr/{TOPLEVEL}/{PKGDIR}/{SUBPATH}',
    :local   => '/usr/local/{TOPLEVEL}/{PKGDIR}/{SUBPATH}',
    :fast    => '/fast/{TOPLEVEL}/{PKGDIR}/{SUBPATH}',
    :cache   => '/cache/{TOPLEVEL}/{PKGDIR}/{SUBPATH}',
    :bulk    => '/bulk/{TOPLEVEL}/{PKGDIR}/{SUBPATH}',
    :lib     => '{LIBDIR}/{TOPLEVEL}/{SUBPATH}',
    :scout_essentials => File.join(Path.caller_lib_dir(__FILE__), "{TOPLEVEL}/{SUBPATH}"),
    :tmp     => '/tmp/{PKGDIR}/{TOPLEVEL}/{SUBPATH}',
    :default => :user
  })
end

.prepend_path(name, map) ⇒ Object



97
98
99
100
# File 'lib/scout/path/find.rb', line 97

def self.prepend_path(name, map)
  path_maps[name] = map
  map_order.unshift(name.to_sym)
end

.sanitize_filename(filename, length = 254) ⇒ Object



15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
# File 'lib/scout/path/util.rb', line 15

def self.sanitize_filename(filename, length = 254)
  if filename.length > length
    if filename =~ /(\..{2,9})$/
      extension = $1
    else
      extension = ''
    end

    post_fix = "--#{filename.length}@#{length}_#{Misc.digest(filename)[0..4]}" + extension

    filename = filename[0..(length - post_fix.length - 1)] << post_fix
  else
    filename
  end
  filename
end

Instance Method Details

#_partsObject



130
131
132
# File 'lib/scout/path/find.rb', line 130

def _parts
  @_parts ||= self.split("/")
end

#_subpathObject



134
135
136
# File 'lib/scout/path/find.rb', line 134

def _subpath
  @subpath ||= _parts.length > 1 ? _parts[1..-1] * "/" : _parts[0] || ""
end

#_toplevelObject



138
139
140
# File 'lib/scout/path/find.rb', line 138

def _toplevel
  @toplevel ||= _parts.length > 1 ? _parts[0] : ""
end

#annotate_found_where(found, where) ⇒ Object



149
150
151
152
153
154
# File 'lib/scout/path/find.rb', line 149

def annotate_found_where(found, where)
  self.annotate(found).tap{|p| 
    p.instance_variable_set("@where", where) 
    p.instance_variable_set("@original", self.dup) 
  }
end

#append_path(name, map) ⇒ Object



112
113
114
115
# File 'lib/scout/path/find.rb', line 112

def append_path(name, map)
  path_maps[name] = map
  map_order.push(name.to_sym)
end

#basenameObject



45
46
47
# File 'lib/scout/path/util.rb', line 45

def basename
  self.annotate(File.basename(self))
end

#digest_strObject



3
4
5
6
7
8
9
10
11
12
# File 'lib/scout/path/digest.rb', line 3

def digest_str
  case
  when File.directory?(self)
    "Directory MD5: #{Misc.digest_str(Dir.glob(File.join(self, "*")))}"
  when self.located? && File.exist?(self)
    "File MD5: #{Misc.digest_file(self)}"
  else
    '\'' << self << '\''
  end
end

#directory?Boolean

Returns:

  • (Boolean)


32
33
34
35
# File 'lib/scout/path/util.rb', line 32

def directory?
  return nil unless self.exist?
  File.directory?(self.find)
end

#dirnameObject



41
42
43
# File 'lib/scout/path/util.rb', line 41

def dirname
  self.annotate(File.dirname(self))
end

#exist?Boolean Also known as: exists?

Returns:

  • (Boolean)


219
220
221
222
223
# File 'lib/scout/path/find.rb', line 219

def exist?
  # OPEN
  found = self.find
  File.exist?(found) || File.directory?(found)
end

#find(where = nil) ⇒ Object



191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
# File 'lib/scout/path/find.rb', line 191

def find(where = nil)
  if located?
    if File.exist?(self)
      return self if located?
    else
      found = Path.exists_file_or_alternatives(self)
      if found
        return self.annotate(found)
      else
        return self if located?
      end
    end
  end

  return find_all if where == 'all' || where == :all

  return follow(where) if where

  map_order.each do |map_name|
    found = follow(map_name, false)

    found = Path.exists_file_or_alternatives(found)
    return annotate_found_where(found, map_name) if found
  end

  return follow(:default)
end

#find_all(caller_lib = nil, search_paths = nil) ⇒ Object



227
228
229
230
231
# File 'lib/scout/path/find.rb', line 227

def find_all(caller_lib = nil, search_paths = nil)
  map_order
    .collect{|where| find(where) }
    .select{|file| file.exist? }.uniq
end

#find_with_extension(extension, *args) ⇒ Object



233
234
235
236
237
238
# File 'lib/scout/path/find.rb', line 233

def find_with_extension(extension, *args)
  found = self.find(*args)
  return found if found.exists?
  found_with_extension = self.set_extension(extension).find
  found_with_extension.exists? ? found_with_extension : found
end

#follow(map_name = :default, annotate = true) ⇒ Object



164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
# File 'lib/scout/path/find.rb', line 164

def follow(map_name = :default, annotate = true)
  IndiferentHash.setup(path_maps)
  map = path_maps[map_name] || Path.path_maps[map_name]
  if map.nil? && String === map_name
    map = File.join(map_name, '{TOPLEVEL}/{SUBPATH}')
  end
  raise "Map not found #{Log.fingerprint map_name} not in #{Log.fingerprint path_maps.keys}" if map.nil?
  while Symbol === map
    map_name = map
    map = path_maps[map_name]
  end
  found = Path.follow(self, map, map_name)

  annotate_found_where(found, map_name)  if annotate

  found
end

#glob(pattern = '*') ⇒ Object



49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
# File 'lib/scout/path/util.rb', line 49

def glob(pattern = '*')
  if self.include? "*"
    self.glob_all
  else
    return [] unless self.exist? 
    found = self.find
    exp = File.join(found, pattern)
    paths = Dir.glob(exp).collect{|f| self.annotate(f) }

    paths.each do |p|
      p.original = File.join(found.original, p.sub(/^#{found}/, ''))
    end if found.original

    paths
  end
end

#glob_all(pattern = nil, caller_lib = nil, search_paths = nil) ⇒ Object



66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
# File 'lib/scout/path/util.rb', line 66

def glob_all(pattern = nil, caller_lib = nil, search_paths = nil)
  search_paths ||= self.path_maps || Path.path_maps
  search_paths = search_paths.dup

  search_paths.keys.collect do |where| 
    found = find(where)
    paths = pattern ? Dir.glob(File.join(found, pattern)) : Dir.glob(found) 

    paths = paths.collect{|p| self.annotate p }

    paths = paths.each do |p|
      p.original = File.join(found.original, p.sub(/^#{found}/, ''))
      p.where = where
    end if found.original and pattern

    paths
  end.flatten.uniq
end

#identifyObject



54
55
56
# File 'lib/scout/resource/path.rb', line 54

def identify
  Resource.identify(self)
end

#join(subpath = nil, prevpath = nil) ⇒ Object Also known as: [], /



35
36
37
38
39
40
41
42
43
44
45
# File 'lib/scout/path.rb', line 35

def join(subpath = nil, prevpath = nil)
  return self if subpath.nil?

  subpath = subpath.to_s if Symbol === subpath
  prevpath = prevpath.to_s if Symbol === prevpath

  subpath = File.join(prevpath.to_s, subpath) if prevpath
  new = self.empty? ? subpath.dup : File.join(self, subpath)
  self.annotate(new)
  new
end

#json(*rest, &block) ⇒ Object



8
9
10
# File 'lib/scout/persist/path.rb', line 8

def json(*rest, &block)
  Open.json(self, *rest, &block)
end

#libdirObject



23
24
25
# File 'lib/scout/path.rb', line 23

def libdir
  @libdir || Path.caller_lib_dir
end

#listObject



72
73
74
75
# File 'lib/scout/resource/path.rb', line 72

def list
  found = produce_and_find('list')
  Open.list(found)
end

#located?Boolean

Returns:

  • (Boolean)


144
145
146
147
# File 'lib/scout/path/find.rb', line 144

def located?
  # OPEN RESOURCE
  self.slice(0,1) == SLASH || (self.slice(0,1) == DOT && self.slice(1,2) == SLASH) # || (resource != Rbbt && (Open.remote?(self) || Open.ssh?(self)))
end

#map_orderObject



31
32
33
# File 'lib/scout/path.rb', line 31

def map_order
  @map_order ||= (path_maps.keys & Path.map_order) + (path_maps.keys - Path.map_order)
end

#marshal(*rest, &block) ⇒ Object



12
13
14
# File 'lib/scout/persist/path.rb', line 12

def marshal(*rest, &block)
  Open.marshal(self, *rest, &block)
end

#no_method_missingObject



2
3
4
5
6
# File 'lib/scout/path/util.rb', line 2

def no_method_missing
  class << self
    undef_method :method_missing
  end
end

#open(*args, &block) ⇒ Object



58
59
60
61
# File 'lib/scout/resource/path.rb', line 58

def open(*args, &block)
  produce
  Open.open(self, *args, &block)
end

#originalObject



160
161
162
# File 'lib/scout/path/find.rb', line 160

def original
  @original
end

#path_mapsObject



27
28
29
# File 'lib/scout/path.rb', line 27

def path_maps
  @path_maps ||= Path.path_maps.dup
end

#pkgdirObject



19
20
21
# File 'lib/scout/path.rb', line 19

def pkgdir
  @pkgdir ||= Path.default_pkgdir
end

#prepend_path(name, map) ⇒ Object



107
108
109
110
# File 'lib/scout/path/find.rb', line 107

def prepend_path(name, map)
  path_maps[name] = map
  map_order.unshift(name.to_sym)
end

#produce(force = false) ⇒ Object

Raises:

  • (@produced)


2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# File 'lib/scout/resource/path.rb', line 2

def produce(force = false)
  raise @produced if Exception === @produced
  return self if ! force && (Open.exist?(self.find) || @produced)
  begin
    if Resource === self.pkgdir
      self.pkgdir.produce self, force
    else
      false
    end
  rescue ResourceNotFound
    @produced = false
  rescue
    message = $!.message
    message = "No exception message" if message.nil? || message.empty?
    Log.warn "Error producing #{self}: #{message}"
    raise $!
  ensure
    @produced = true if @produced.nil?
  end
end

#produce_and_find(extension = nil, *args) ⇒ Object



36
37
38
39
40
41
42
43
44
45
46
47
# File 'lib/scout/resource/path.rb', line 36

def produce_and_find(extension = nil, *args)
  found = if extension
            found = find_with_extension(extension, *args)
            found.exists? ? found : produce_with_extension(extension, *args)
          else
            found = find
            found.exists? ? found : produce(*args)
          end
  raise "Not found: #{self}" unless found

  found
end

#produce_with_extension(extension, *args) ⇒ Object



23
24
25
26
27
28
29
30
31
32
33
34
# File 'lib/scout/resource/path.rb', line 23

def produce_with_extension(extension, *args)
  begin
    self.produce(*args)
  rescue Exception
    exception = $!
    begin
      self.set_extension(extension).produce(*args)
    rescue Exception
      raise exception
    end
  end
end

#readObject



63
64
65
66
# File 'lib/scout/resource/path.rb', line 63

def read
  produce
  Open.read(self)
end

#relocateObject



49
50
51
52
# File 'lib/scout/resource/path.rb', line 49

def relocate
  return self if Open.exists?(self)
  Resource.relocate(self)
end

#remove_extension(extension = nil) ⇒ Object



93
94
95
96
97
98
99
# File 'lib/scout/path/util.rb', line 93

def remove_extension(extension = nil)
  if extension.nil?
    unset_extension
  else
    self.annotate(self.sub(/\.#{extension}$/,''))
  end
end

#replace_extension(new_extension = nil, multiple = false) ⇒ Object



101
102
103
104
105
106
107
108
109
110
111
# File 'lib/scout/path/util.rb', line 101

def replace_extension(new_extension = nil, multiple = false)
  if String === multiple
    new_path = self.sub(/(\.[^\.\/]{1,5})(.#{multiple})?$/,'')
  elsif multiple
    new_path = self.sub(/(\.[^\.\/]{1,5})+$/,'')
  else
    new_path = self.sub(/\.[^\.\/]{1,5}$/,'')
  end
  new_path = new_path + "." + new_extension.to_s
  self.annotate(new_path)
end

#set_extension(extension) ⇒ Object



85
86
87
# File 'lib/scout/path/util.rb', line 85

def set_extension(extension)
  self.annotate(self + ".#{extension}")
end

#sub(*args) ⇒ Object



37
38
39
# File 'lib/scout/path/util.rb', line 37

def sub(*args)
  self.annotate super(*args)
end

#unset_extensionObject



89
90
91
# File 'lib/scout/path/util.rb', line 89

def unset_extension
  self.annotate(self.split(".")[0..-2] * ".")
end

#whereObject



156
157
158
# File 'lib/scout/path/find.rb', line 156

def where
  @where
end

#write(*args, &block) ⇒ Object



68
69
70
# File 'lib/scout/resource/path.rb', line 68

def write(*args, &block)
  Open.write(self.find, *args, &block)
end

#yaml(*rest, &block) ⇒ Object



4
5
6
# File 'lib/scout/persist/path.rb', line 4

def yaml(*rest, &block)
  Open.yaml(self, *rest, &block)
end