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 CHANGED
@@ -1,4 +1,4 @@
1
1
  ---
2
2
  :minor: 0
3
- :patch: 6
3
+ :patch: 7
4
4
  :major: 0
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.6"
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-05}
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",
@@ -2,7 +2,7 @@ module FSSM::Backends
2
2
  class Polling
3
3
  def initialize(options={})
4
4
  @handlers = []
5
- @latency = options[:latency] || 1
5
+ @latency = options[:latency] || 1.5
6
6
  end
7
7
 
8
8
  def add_path(path, preload=true)
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
@@ -28,9 +28,8 @@ module FSSM
28
28
  end
29
29
 
30
30
  require 'thread'
31
- require 'pathname'
32
31
 
33
- require 'fssm/ext'
32
+ require 'fssm/pathname'
34
33
  require 'fssm/support'
35
34
  require 'fssm/tree'
36
35
  require 'fssm/path'
@@ -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