/usr/lib/ruby/1.8/fssm/tree.rb is in libfssm-ruby1.8 0.1.4-2.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 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 34 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 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 | module FSSM::Tree
module NodeBase
def initialize
@children = {}
end
protected
def child(segment)
@children["#{segment}"]
end
def child!(segment)
(@children["#{segment}"] ||= Node.new)
end
def has_child?(segment)
@children.has_key?("#{segment}")
end
def remove_child(segment)
@children.delete("#{segment}")
end
def remove_children
@children.clear
end
end
module NodeEnumerable
include NodeBase
include Enumerable
def each(prefix=nil, &block)
@children.each do |segment, node|
cprefix = prefix ?
FSSM::Pathname.for(prefix).join(segment) :
FSSM::Pathname.for(segment)
block.call([cprefix, node])
node.each(cprefix, &block)
end
end
end
module NodeInsertion
include NodeBase
def unset(path)
key = key_segments(path)
if key.empty?
remove_children
return nil
end
segment = key.pop
node = descendant(key)
return unless node
node.remove_child(segment)
nil
end
def set(path)
node = descendant!(path)
node.from_path(path).mtime
end
protected
def key_segments(key)
return key if key.is_a?(Array)
FSSM::Pathname.for(key).segments
end
def descendant(path)
recurse(path, false)
end
def descendant!(path)
recurse(path, true)
end
def recurse(key, create=false)
key = key_segments(key)
node = self
until key.empty?
segment = key.shift
node = create ? node.child!(segment) : node.child(segment)
return nil unless node
end
node
end
end
module CacheDebug
def set(path)
FSSM.dbg("Cache#set(#{path})")
super
end
def unset(path)
FSSM.dbg("Cache#unset(#{path})")
super
end
def ftype(ft)
FSSM.dbg("Cache#ftype(#{ft})")
super
end
end
class Node
include NodeBase
include NodeEnumerable
attr_accessor :mtime
attr_accessor :ftype
def <=>(other)
return unless other.is_a?(::FSSM::Tree::Node)
self.mtime <=> other.mtime
end
def from_path(path)
path = FSSM::Pathname.for(path)
@ftype = path.ftype
# this handles bad symlinks without failing. why handle bad symlinks at
# all? well, we could still be interested in their creation and deletion.
@mtime = path.symlink? ? Time.at(0) : path.mtime
self
end
end
class Cache
include NodeBase
include NodeEnumerable
include NodeInsertion
include CacheDebug if $DEBUG
def set(path)
# all paths set from this level need to be absolute
# realpath will fail on broken links
path = FSSM::Pathname.for(path).expand_path
super(path)
end
def files
ftype('file')
end
def directories
ftype('directory')
end
def links
ftype('link')
end
alias symlinks links
private
def ftype(ft)
inject({}) do |hash, (path, node)|
hash["#{path}"] = node.mtime if node.ftype == ft
hash
end
end
end
end
|