ttilley-fssm 0.0.6 → 0.0.7
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.
- data/VERSION.yml +1 -1
- data/fssm.gemspec +8 -4
- data/lib/fssm/backends/polling.rb +1 -1
- data/lib/fssm/path.rb +2 -2
- data/lib/fssm/pathname.rb +350 -0
- data/lib/fssm/state.rb +3 -3
- data/lib/fssm/tree.rb +5 -5
- data/lib/fssm.rb +1 -2
- data/{prof-cache.rb → profile/prof-cache.rb} +3 -3
- data/profile/prof-fssm-pathname.html +1119 -0
- data/profile/prof-pathname.rb +68 -0
- data/profile/prof-plain-pathname.html +909 -0
- data/profile/prof.html +2163 -0
- metadata +10 -5
- data/lib/fssm/ext.rb +0 -37
data/VERSION.yml
CHANGED
data/fssm.gemspec
CHANGED
|
@@ -5,11 +5,11 @@
|
|
|
5
5
|
|
|
6
6
|
Gem::Specification.new do |s|
|
|
7
7
|
s.name = %q{fssm}
|
|
8
|
-
s.version = "0.0.
|
|
8
|
+
s.version = "0.0.7"
|
|
9
9
|
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
|
11
11
|
s.authors = ["Travis Tilley"]
|
|
12
|
-
s.date = %q{2009-09-
|
|
12
|
+
s.date = %q{2009-09-07}
|
|
13
13
|
s.description = %q{file system state monitor}
|
|
14
14
|
s.email = %q{ttilley@gmail.com}
|
|
15
15
|
s.extra_rdoc_files = [
|
|
@@ -28,14 +28,18 @@ Gem::Specification.new do |s|
|
|
|
28
28
|
"lib/fssm.rb",
|
|
29
29
|
"lib/fssm/backends/fsevents.rb",
|
|
30
30
|
"lib/fssm/backends/polling.rb",
|
|
31
|
-
"lib/fssm/ext.rb",
|
|
32
31
|
"lib/fssm/fsevents.rb",
|
|
33
32
|
"lib/fssm/monitor.rb",
|
|
34
33
|
"lib/fssm/path.rb",
|
|
34
|
+
"lib/fssm/pathname.rb",
|
|
35
35
|
"lib/fssm/state.rb",
|
|
36
36
|
"lib/fssm/support.rb",
|
|
37
37
|
"lib/fssm/tree.rb",
|
|
38
|
-
"prof-cache.rb",
|
|
38
|
+
"profile/prof-cache.rb",
|
|
39
|
+
"profile/prof-fssm-pathname.html",
|
|
40
|
+
"profile/prof-pathname.rb",
|
|
41
|
+
"profile/prof-plain-pathname.html",
|
|
42
|
+
"profile/prof.html",
|
|
39
43
|
"spec/path_spec.rb",
|
|
40
44
|
"spec/root/duck/quack.txt",
|
|
41
45
|
"spec/root/file.css",
|
data/lib/fssm/path.rb
CHANGED
|
@@ -75,12 +75,12 @@ class FSSM::Path
|
|
|
75
75
|
end
|
|
76
76
|
|
|
77
77
|
def split_path(path)
|
|
78
|
-
path = Pathname.for(path)
|
|
78
|
+
path = FSSM::Pathname.for(path)
|
|
79
79
|
[@path, (path.relative? ? path : path.relative_path_from(@path))]
|
|
80
80
|
end
|
|
81
81
|
|
|
82
82
|
def set_path(path)
|
|
83
|
-
path = Pathname.for(path)
|
|
83
|
+
path = FSSM::Pathname.for(path)
|
|
84
84
|
raise FSSM::FileNotFoundError, "#{path}" unless path.exist?
|
|
85
85
|
@path = path.realpath
|
|
86
86
|
end
|
|
@@ -0,0 +1,350 @@
|
|
|
1
|
+
# The bundled ruby pathname library is a slow and hideous beast.
|
|
2
|
+
# There. I said it. This version is based on pathname3.
|
|
3
|
+
|
|
4
|
+
module FSSM
|
|
5
|
+
class Pathname < String
|
|
6
|
+
|
|
7
|
+
SEPARATOR = Regexp.quote(File::SEPARATOR)
|
|
8
|
+
|
|
9
|
+
if File::ALT_SEPARATOR
|
|
10
|
+
ALT_SEPARATOR = Regexp.quote(File::ALT_SEPARATOR)
|
|
11
|
+
SEPARATOR_PAT = Regexp.compile("[#{SEPARATOR}#{ALT_SEPARATOR}]")
|
|
12
|
+
else
|
|
13
|
+
SEPARATOR_PAT = Regexp.compile(SEPARATOR)
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
if RUBY_PLATFORM =~ /(:?mswin|mingw|bccwin)/
|
|
17
|
+
PREFIX_PAT = Regexp.compile("^([A-Za-z]:#{SEPARATOR_PAT})")
|
|
18
|
+
else
|
|
19
|
+
PREFIX_PAT = Regexp.compile("^(#{SEPARATOR_PAT})")
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
class << self
|
|
23
|
+
def for(path)
|
|
24
|
+
path = path.is_a?(::FSSM::Pathname) ? path : new(path)
|
|
25
|
+
path.dememo
|
|
26
|
+
path
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def initialize(path)
|
|
31
|
+
if path =~ %r{\0}
|
|
32
|
+
raise ArgumentError, "path cannot contain ASCII NULLs"
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
dememo
|
|
36
|
+
|
|
37
|
+
super(path)
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def to_path
|
|
41
|
+
self
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def to_s
|
|
45
|
+
"#{self}"
|
|
46
|
+
end
|
|
47
|
+
alias to_str to_s
|
|
48
|
+
|
|
49
|
+
def to_a
|
|
50
|
+
return @segments if @segments
|
|
51
|
+
set_prefix_and_names
|
|
52
|
+
@segments = @names.dup
|
|
53
|
+
@segments.delete('.')
|
|
54
|
+
@segments.unshift(@prefix) unless @prefix.empty?
|
|
55
|
+
@segments
|
|
56
|
+
end
|
|
57
|
+
alias segments to_a
|
|
58
|
+
|
|
59
|
+
def each_filename(&block)
|
|
60
|
+
to_a.each(&block)
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def ascend
|
|
64
|
+
parts = to_a
|
|
65
|
+
parts.length.downto(1) do |i|
|
|
66
|
+
yield self.class.join(parts[0, i])
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def descend
|
|
71
|
+
parts = to_a
|
|
72
|
+
1.upto(parts.length) do |i|
|
|
73
|
+
yield self.class.join(parts[0, i])
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
def root?
|
|
78
|
+
set_prefix_and_names
|
|
79
|
+
@names.empty? && !@prefix.empty?
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
def parent
|
|
83
|
+
self + '..'
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
def relative?
|
|
87
|
+
set_prefix_and_names
|
|
88
|
+
@prefix.empty?
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
def absolute?
|
|
92
|
+
!relative?
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
def +(path)
|
|
96
|
+
dup << path
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
def <<(path)
|
|
100
|
+
replace(join(path).cleanpath!)
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
def cleanpath!
|
|
104
|
+
parts = to_a
|
|
105
|
+
final = []
|
|
106
|
+
|
|
107
|
+
parts.each do |part|
|
|
108
|
+
case part
|
|
109
|
+
when '.' then next
|
|
110
|
+
when '..' then
|
|
111
|
+
case final.last
|
|
112
|
+
when '..' then final.push('..')
|
|
113
|
+
when nil then final.push('..')
|
|
114
|
+
else final.pop
|
|
115
|
+
end
|
|
116
|
+
else final.push(part)
|
|
117
|
+
end
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
replace(final.empty? ? Dir.pwd : File.join(*final))
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
def cleanpath
|
|
124
|
+
dup.cleanpath!
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
def realpath
|
|
128
|
+
raise unless self.exist?
|
|
129
|
+
|
|
130
|
+
if File.symlink?(self)
|
|
131
|
+
file = self.dup
|
|
132
|
+
|
|
133
|
+
while true
|
|
134
|
+
file = File.join(File.dirname(file), File.readlink(file))
|
|
135
|
+
break unless File.symlink?(file)
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
self.class.new(file).clean
|
|
139
|
+
else
|
|
140
|
+
self.class.new(Dir.pwd) + self
|
|
141
|
+
end
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
def relative_path_from(base)
|
|
145
|
+
base = self.class.for(base)
|
|
146
|
+
|
|
147
|
+
if self.absolute? != base.absolute?
|
|
148
|
+
raise ArgumentError, 'no relative path between a relative and absolute'
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
if self.prefix != base.prefix
|
|
152
|
+
raise ArgumentError, "different prefix: #{@prefix.inspect} and #{base.prefix.inspect}"
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
base = base.cleanpath!.segments
|
|
156
|
+
dest = dup.cleanpath!.segments
|
|
157
|
+
|
|
158
|
+
while !dest.empty? && !base.empty? && dest[0] == base[0]
|
|
159
|
+
base.shift
|
|
160
|
+
dest.shift
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
base.shift if base[0] == '.'
|
|
164
|
+
dest.shift if dest[0] == '.'
|
|
165
|
+
|
|
166
|
+
if base.include?('..')
|
|
167
|
+
raise ArgumentError, "base directory may not contain '..'"
|
|
168
|
+
end
|
|
169
|
+
|
|
170
|
+
path = base.fill('..') + dest
|
|
171
|
+
path = self.class.join(*path)
|
|
172
|
+
path = self.class.new('.') if path.empty?
|
|
173
|
+
|
|
174
|
+
path
|
|
175
|
+
end
|
|
176
|
+
|
|
177
|
+
def replace(path)
|
|
178
|
+
if path =~ %r{\0}
|
|
179
|
+
raise ArgumentError, "path cannot contain ASCII NULLs"
|
|
180
|
+
end
|
|
181
|
+
|
|
182
|
+
dememo
|
|
183
|
+
|
|
184
|
+
super(path)
|
|
185
|
+
end
|
|
186
|
+
|
|
187
|
+
def unlink
|
|
188
|
+
Dir.unlink(self)
|
|
189
|
+
true
|
|
190
|
+
rescue Errno::ENOTDIR
|
|
191
|
+
File.unlink(self)
|
|
192
|
+
true
|
|
193
|
+
end
|
|
194
|
+
|
|
195
|
+
def prefix
|
|
196
|
+
set_prefix_and_names
|
|
197
|
+
@prefix
|
|
198
|
+
end
|
|
199
|
+
|
|
200
|
+
def names
|
|
201
|
+
set_prefix_and_names
|
|
202
|
+
@names
|
|
203
|
+
end
|
|
204
|
+
|
|
205
|
+
def dememo
|
|
206
|
+
@set = nil
|
|
207
|
+
@segments = nil
|
|
208
|
+
@prefix = nil
|
|
209
|
+
@names = nil
|
|
210
|
+
end
|
|
211
|
+
|
|
212
|
+
private
|
|
213
|
+
|
|
214
|
+
def set_prefix_and_names
|
|
215
|
+
return if @set
|
|
216
|
+
|
|
217
|
+
@names = []
|
|
218
|
+
|
|
219
|
+
if (match = PREFIX_PAT.match(self))
|
|
220
|
+
@prefix = match[0].to_s
|
|
221
|
+
@names += match.post_match.split(SEPARATOR_PAT)
|
|
222
|
+
else
|
|
223
|
+
@prefix = ''
|
|
224
|
+
@names += self.split(SEPARATOR_PAT)
|
|
225
|
+
end
|
|
226
|
+
|
|
227
|
+
@names.compact!
|
|
228
|
+
@names.delete('')
|
|
229
|
+
|
|
230
|
+
@set = true
|
|
231
|
+
end
|
|
232
|
+
|
|
233
|
+
end
|
|
234
|
+
|
|
235
|
+
class Pathname
|
|
236
|
+
class << self
|
|
237
|
+
def glob(pattern, flags=0)
|
|
238
|
+
dirs = Dir.glob(pattern, flags)
|
|
239
|
+
dirs.map! {|path| new(path)}
|
|
240
|
+
|
|
241
|
+
if block_given?
|
|
242
|
+
dirs.each {|dir| yield dir}
|
|
243
|
+
nil
|
|
244
|
+
else
|
|
245
|
+
dirs
|
|
246
|
+
end
|
|
247
|
+
end
|
|
248
|
+
|
|
249
|
+
def [](pattern)
|
|
250
|
+
Dir[pattern].map! {|path| new(path)}
|
|
251
|
+
end
|
|
252
|
+
|
|
253
|
+
def pwd
|
|
254
|
+
new(Dir.pwd)
|
|
255
|
+
end
|
|
256
|
+
end
|
|
257
|
+
|
|
258
|
+
def entries; Dir.entries(self).map! {|e| FSSM::Pathname.new(e) }; end
|
|
259
|
+
def mkdir(mode = 0777); Dir.mkdir(self, mode); end
|
|
260
|
+
def opendir(&blk); Dir.open(self, &blk); end
|
|
261
|
+
def rmdir; Dir.rmdir(self); end
|
|
262
|
+
|
|
263
|
+
def chdir
|
|
264
|
+
blk = lambda { yield self } if block_given?
|
|
265
|
+
Dir.chdir(self, &blk)
|
|
266
|
+
end
|
|
267
|
+
end
|
|
268
|
+
|
|
269
|
+
class Pathname
|
|
270
|
+
def blockdev?; FileTest.blockdev?(self); end
|
|
271
|
+
def chardev?; FileTest.chardev?(self); end
|
|
272
|
+
def directory?; FileTest.directory?(self); end
|
|
273
|
+
def executable?; FileTest.executable?(self); end
|
|
274
|
+
def executable_real?; FileTest.executable_real?(self); end
|
|
275
|
+
def exists?; FileTest.exists?(self); end
|
|
276
|
+
def file?; FileTest.file?(self); end
|
|
277
|
+
def grpowned?; FileTest.grpowned?(self); end
|
|
278
|
+
def owned?; FileTest.owned?(self); end
|
|
279
|
+
def pipe?; FileTest.pipe?(self); end
|
|
280
|
+
def readable?; FileTest.readable?(self); end
|
|
281
|
+
def readable_real?; FileTest.readable_real?(self); end
|
|
282
|
+
def setgid?; FileTest.setgit?(self); end
|
|
283
|
+
def setuid?; FileTest.setuid?(self); end
|
|
284
|
+
def socket?; FileTest.socket?(self); end
|
|
285
|
+
def sticky?; FileTest.sticky?(self); end
|
|
286
|
+
def symlink?; FileTest.symlink?(self); end
|
|
287
|
+
def world_readable?; FileTest.world_readable?(self); end
|
|
288
|
+
def world_writable?; FileTest.world_writable?(self); end
|
|
289
|
+
def writable?; FileTest.writable?(self); end
|
|
290
|
+
def writable_real?; FileTest.writable_real?(self); end
|
|
291
|
+
def zero?; FileTest.zero?(self); end
|
|
292
|
+
|
|
293
|
+
alias exist? exists?
|
|
294
|
+
end
|
|
295
|
+
|
|
296
|
+
class Pathname
|
|
297
|
+
def atime; File.atime(self); end
|
|
298
|
+
def ctime; File.ctime(self); end
|
|
299
|
+
def ftype; File.ftype(self); end
|
|
300
|
+
def lstat; File.lstat(self); end
|
|
301
|
+
def mtime; File.mtime(self); end
|
|
302
|
+
def stat; File.stat(self); end
|
|
303
|
+
def utime(atime, mtime); File.utime(self, atime, mtime); end
|
|
304
|
+
end
|
|
305
|
+
|
|
306
|
+
class Pathname
|
|
307
|
+
class << self
|
|
308
|
+
def join(*parts)
|
|
309
|
+
new(File.join(*parts.reject {|p| p.empty? }))
|
|
310
|
+
end
|
|
311
|
+
end
|
|
312
|
+
|
|
313
|
+
def basename; self.class.new(File.basename(self)); end
|
|
314
|
+
def chmod(mode); File.chmod(mode, self); end
|
|
315
|
+
def chown(owner, group); File.chown(owner, group, self); end
|
|
316
|
+
def dirname; self.class.new(File.dirname(self)); end
|
|
317
|
+
def expand_path(from = nil); self.class.new(File.expand_path(self, from)); end
|
|
318
|
+
def extname; File.extname(self); end
|
|
319
|
+
def fnmatch?(pat, flags = 0); File.fnmatch(pat, self, flags); end
|
|
320
|
+
def join(*parts); self.class.join(self, *parts); end
|
|
321
|
+
def lchmod(mode); File.lchmod(mode, self); end
|
|
322
|
+
def lchown(owner, group); File.lchown(owner, group, self); end
|
|
323
|
+
def link(to); File.link(self, to); end
|
|
324
|
+
def open(mode = 'r', perm = nil, &blk); File.open(self, mode, perm, &blk); end
|
|
325
|
+
def readlink; self.class.new(File.readlink(self)); end
|
|
326
|
+
def rename(to); File.rename(self, to); replace(to); end
|
|
327
|
+
def size; File.size(self); end
|
|
328
|
+
def size?; File.size?(self); end
|
|
329
|
+
def symlink(to); File.symlink(self, to); end
|
|
330
|
+
def truncate; File.truncate(self); end
|
|
331
|
+
end
|
|
332
|
+
|
|
333
|
+
class Pathname
|
|
334
|
+
def mkpath; self.class.new(FileUtils.mkpath(self)); end
|
|
335
|
+
def rmtree; self.class.new(FileUtils.rmtree(self).first); end
|
|
336
|
+
def touch; self.class.new(FileUtils.touch(self).first); end
|
|
337
|
+
end
|
|
338
|
+
|
|
339
|
+
class Pathname
|
|
340
|
+
def each_line(sep = $/, &blk); IO.foreach(self, sep, &blk); end
|
|
341
|
+
def read(len = nil, off = 0); IO.read(self, len, off); end
|
|
342
|
+
def readlines(sep = $/); IO.readlines(self, sep); end
|
|
343
|
+
def sysopen(mode = 'r', perm = nil); IO.sysopen(self, mode, perm); end
|
|
344
|
+
end
|
|
345
|
+
|
|
346
|
+
class Pathname
|
|
347
|
+
def find; Find.find(self) {|path| yield FSSM::Pathname.new(path) }; end
|
|
348
|
+
end
|
|
349
|
+
|
|
350
|
+
end
|
data/lib/fssm/state.rb
CHANGED
|
@@ -32,7 +32,7 @@ class FSSM::State
|
|
|
32
32
|
end
|
|
33
33
|
|
|
34
34
|
def recache(base)
|
|
35
|
-
base = Pathname.for(base)
|
|
35
|
+
base = FSSM::Pathname.for(base)
|
|
36
36
|
previous = @cache.files
|
|
37
37
|
snapshot(base)
|
|
38
38
|
current = @cache.files
|
|
@@ -40,13 +40,13 @@ class FSSM::State
|
|
|
40
40
|
end
|
|
41
41
|
|
|
42
42
|
def snapshot(base)
|
|
43
|
-
base = Pathname.for(base)
|
|
43
|
+
base = FSSM::Pathname.for(base)
|
|
44
44
|
@cache.unset(base)
|
|
45
45
|
@path.glob.each {|glob| add_glob(base, glob)}
|
|
46
46
|
end
|
|
47
47
|
|
|
48
48
|
def add_glob(base, glob)
|
|
49
|
-
Pathname.glob(base.join(glob)).each do |fn|
|
|
49
|
+
FSSM::Pathname.glob(base.join(glob)).each do |fn|
|
|
50
50
|
@cache.set(fn)
|
|
51
51
|
end
|
|
52
52
|
end
|
data/lib/fssm/tree.rb
CHANGED
|
@@ -34,8 +34,8 @@ module FSSM::Tree
|
|
|
34
34
|
def each(prefix=nil, &block)
|
|
35
35
|
@children.each do |segment, node|
|
|
36
36
|
cprefix = prefix ?
|
|
37
|
-
Pathname.for(prefix).join(segment) :
|
|
38
|
-
Pathname.for(segment)
|
|
37
|
+
FSSM::Pathname.for(prefix).join(segment) :
|
|
38
|
+
FSSM::Pathname.for(segment)
|
|
39
39
|
block.call(cprefix, node)
|
|
40
40
|
node.each(cprefix, &block)
|
|
41
41
|
end
|
|
@@ -72,7 +72,7 @@ module FSSM::Tree
|
|
|
72
72
|
|
|
73
73
|
def key_segments(key)
|
|
74
74
|
return key if key.is_a?(Array)
|
|
75
|
-
Pathname.for(key).segments
|
|
75
|
+
FSSM::Pathname.for(key).segments
|
|
76
76
|
end
|
|
77
77
|
|
|
78
78
|
def descendant(path)
|
|
@@ -127,7 +127,7 @@ module FSSM::Tree
|
|
|
127
127
|
end
|
|
128
128
|
|
|
129
129
|
def from_path(path)
|
|
130
|
-
path = Pathname.for(path)
|
|
130
|
+
path = FSSM::Pathname.for(path)
|
|
131
131
|
@ftype = path.ftype
|
|
132
132
|
# this handles bad symlinks without failing. why handle bad symlinks at
|
|
133
133
|
# all? well, we could still be interested in their creation and deletion.
|
|
@@ -145,7 +145,7 @@ module FSSM::Tree
|
|
|
145
145
|
def set(path)
|
|
146
146
|
# all paths set from this level need to be absolute
|
|
147
147
|
# realpath will fail on broken links
|
|
148
|
-
path = Pathname.for(path).expand_path
|
|
148
|
+
path = FSSM::Pathname.for(path).expand_path
|
|
149
149
|
super(path)
|
|
150
150
|
end
|
|
151
151
|
|
data/lib/fssm.rb
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
$:.unshift(File.join(File.dirname(__FILE__), 'lib'))
|
|
1
|
+
$:.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
|
2
2
|
|
|
3
3
|
require 'fssm'
|
|
4
4
|
|
|
5
5
|
require 'rubygems'
|
|
6
6
|
require 'ruby-prof'
|
|
7
7
|
|
|
8
|
-
$test_path = Pathname.new('
|
|
9
|
-
$test_files = Pathname.glob(File.join($test_path, '**', '*'))
|
|
8
|
+
$test_path = FSSM::Pathname.new('..').expand_path
|
|
9
|
+
$test_files = FSSM::Pathname.glob(File.join($test_path, '**', '*'))
|
|
10
10
|
|
|
11
11
|
RubyProf.start
|
|
12
12
|
RubyProf.pause
|