file-tail 0.1.4 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGES CHANGED
@@ -1,3 +1,13 @@
1
+ 2007-03-30 * 1.0.0 * Bugfix: David.Barzilay@swisscom.com reported, that file
2
+ tails may skip some log file lines, after rotating it. I
3
+ think, І fixed that problem.
4
+ I added a after_reopen callback as well, that is called
5
+ after reopening of the tailed file has occured.
6
+ * Removed rewind/wind methods even earlier than planned: I
7
+ placed the deprecation warning for rewind method in File
8
+ instead of File::Tail, which caused rewind to stop working
9
+ completely after loading file/tail. Duh! I blame vim's
10
+ matchit, because it jumped to the wrong end keyword.
1
11
  2007-02-08 * 0.1.4 * Renamed rewind method to backward, and wind method to
2
12
  forward, because someone already had the good idea to name
3
13
  a method IO#rewind, which was overwritten by the mixed in
data/Rakefile CHANGED
@@ -36,45 +36,19 @@ task :clean do
36
36
  end
37
37
 
38
38
  spec = Gem::Specification.new do |s|
39
-
40
- #### Basic information.
41
-
42
39
  s.name = 'file-tail'
43
40
  s.version = PKG_VERSION
44
41
  s.summary = "File::Tail for Ruby"
45
42
  s.description = "Library to tail files in Ruby"
46
43
 
47
- #### Dependencies and requirements.
48
-
49
- #s.add_dependency('log4r', '> 1.0.4')
50
- #s.requirements << ""
51
-
52
44
  s.files = PKG_FILES
53
45
 
54
- #### C code extensions.
55
-
56
- #s.extensions << "ext/extconf.rb"
57
-
58
- #### Load-time details: library and application (you will need one or both).
59
-
60
- s.require_path = 'lib' # Use these for libraries.
61
- #s.autorequire = 'file/tail'
62
-
63
- #s.bindir = "bin" # Use these for applications.
64
- #s.executables = ["bla.rb"]
65
- #s.default_executable = "bla.rb"
66
-
67
- #### Documentation and testing.
46
+ s.require_path = 'lib'
68
47
 
69
48
  s.has_rdoc = true
70
- #s.extra_rdoc_files = rd.rdoc_files.reject { |fn| fn =~ /\.rb$/ }.to_a
71
- s.rdoc_options <<
72
- '--title' << 'File::Tail' <<
73
- # '--line-numbers'
49
+ s.rdoc_options << '--title' << 'File::Tail' << '--line-numbers'
74
50
  s.test_files << 'tests/test_file-tail.rb'
75
51
 
76
- #### Author and project details.
77
-
78
52
  s.author = "Florian Frank"
79
53
  s.email = "flori@ping.de"
80
54
  s.homepage = "http://file-tail.rubyforge.org"
@@ -86,4 +60,23 @@ Rake::GemPackageTask.new(spec) do |pkg|
86
60
  pkg.package_files += PKG_FILES
87
61
  end
88
62
 
63
+ desc m = "Writing version information for #{PKG_VERSION}"
64
+ task :version do
65
+ puts m
66
+ File.open(File.join('lib', 'file', 'tail', 'version.rb'), 'w') do |v|
67
+ v.puts <<EOT
68
+ class File
69
+ module Tail
70
+ # File::Tail version
71
+ VERSION = '#{PKG_VERSION}'
72
+ VERSION_ARRAY = VERSION.split(/\\./).map { |x| x.to_i } # :nodoc:
73
+ VERSION_MAJOR = VERSION_ARRAY[0] # :nodoc:
74
+ VERSION_MINOR = VERSION_ARRAY[1] # :nodoc:
75
+ VERSION_BUILD = VERSION_ARRAY[2] # :nodoc:
76
+ end
77
+ end
78
+ EOT
79
+ end
80
+ end
81
+
89
82
  task :release => [ :clean, :package ]
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.1.4
1
+ 1.0.0
data/install.rb CHANGED
@@ -8,12 +8,15 @@ include Config
8
8
 
9
9
  cd 'lib' do
10
10
  libdir = CONFIG["sitelibdir"]
11
- subdir = 'file'
12
- filename = 'tail.rb'
13
11
 
14
- dest = File.join(libdir, subdir)
12
+ dest = File.join(libdir, 'file')
15
13
  mkdir_p(dest)
16
- file = File.join('file', filename)
14
+ file = File.join('file', 'tail.rb')
15
+ install(file, dest)
16
+
17
+ dest = File.join(dest, 'tail')
18
+ mkdir_p(dest)
19
+ file = File.join('file', 'tail', 'version.rb')
17
20
  install(file, dest)
18
21
  end
19
22
  # vim: set et sw=2 ts=2:
data/lib/file/tail.rb CHANGED
@@ -1,4 +1,5 @@
1
1
  #
2
+ require 'file/tail/version'
2
3
  # = File::Tail - Tailing files in Ruby
3
4
  #
4
5
  # == Description
@@ -92,8 +93,11 @@ class File
92
93
  # in the logfile for 10 lines at the start. The buffersize
93
94
  # for going backwards can be set with the
94
95
  # * <code>:bufsiz => 8192</code> option.
95
- # Every attribute of File::Tail can be set with a
96
- # <code>:attributename => value</code> option.
96
+ # To define a callback, that will be called after a reopening occurs, use:
97
+ # * <code>:after_reopen => lambda { |file| p file }</code>
98
+ #
99
+ # Every attribute of File::Tail can be set with a <code>:attributename =>
100
+ # value</code> option.
97
101
  def self.open(filename, opts = {}) # :yields: file
98
102
  file = new filename
99
103
  opts.each do |o, v|
@@ -111,6 +115,9 @@ class File
111
115
  elsif forward = opts[:forward] || opts[:wind]
112
116
  file.forward(forward)
113
117
  end
118
+ if opts[:after_reopen]
119
+ file.after_reopen &opts[:after_reopen]
120
+ end
114
121
  if block_given?
115
122
  yield file
116
123
  nil
@@ -187,6 +194,13 @@ class File
187
194
  # <code>suspicious_interval</code> seconds of silence.
188
195
  attr_accessor :reopen_suspicious
189
196
 
197
+ # The callback is called with _self_ as an argument after a reopen has
198
+ # occured. This allows a tailing script to find out, if a logfile has been
199
+ # rotated.
200
+ def after_reopen(&block)
201
+ @after_reopen = block
202
+ end
203
+
190
204
  # This attribute is the invterval in seconds before File::Tail
191
205
  # gets suspicious that something has happend to it's tailed file
192
206
  # and an attempt to reopen it is made.
@@ -215,12 +229,6 @@ class File
215
229
  self
216
230
  end
217
231
 
218
- # The wind method is deprecated, use forward instead.
219
- def wind(*args)
220
- warn "File::Tail#wind method is deprecated, use forward instead"
221
- forward *args
222
- end
223
-
224
232
  # Rewind the last <code>n</code> lines of this file, starting
225
233
  # from the end. The default is to start tailing directly from the
226
234
  # end of the file.
@@ -279,6 +287,7 @@ class File
279
287
  # call doesn't return, but yields to block for every new line read from
280
288
  # this file for ever.
281
289
  def tail(n = nil, &block) # :yields: line
290
+ @n = n
282
291
  result = []
283
292
  array_result = false
284
293
  unless block
@@ -289,10 +298,15 @@ class File
289
298
  loop do
290
299
  begin
291
300
  restat
292
- read_line(n, &block)
301
+ read_line(&block)
293
302
  redo
294
303
  rescue ReopenException => e
304
+ until eof? || @n == 0
305
+ block.call readline
306
+ @n -= 1 if @n
307
+ end
295
308
  reopen_file(e.mode)
309
+ @after_reopen.call self if @after_reopen
296
310
  rescue ReturnException
297
311
  return array_result ? result : nil
298
312
  end
@@ -301,12 +315,13 @@ class File
301
315
 
302
316
  private
303
317
 
304
- def read_line(n)
305
- if n
306
- n.times do
318
+ def read_line
319
+ if @n
320
+ until @n == 0
307
321
  yield readline
308
322
  @lines += 1
309
323
  @no_read = 0
324
+ @n -= 1
310
325
  debug
311
326
  end
312
327
  raise ReturnException
@@ -323,8 +338,7 @@ class File
323
338
  raise BreakException if @break_if_eof
324
339
  raise ReturnException if @return_if_eof
325
340
  sleep_interval
326
- rescue Errno::ENOENT
327
- rescue Errno::ESTALE
341
+ rescue Errno::ENOENT, Errno::ESTALE
328
342
  raise ReopenException
329
343
  end
330
344
 
@@ -354,8 +368,7 @@ class File
354
368
  else
355
369
  @stat = stat
356
370
  end
357
- rescue Errno::ENOENT
358
- rescue Errno::ESTALE
371
+ rescue Errno::ENOENT, Errno::ESTALE
359
372
  raise ReopenException
360
373
  end
361
374
 
@@ -384,8 +397,7 @@ class File
384
397
  if mode == :bottom
385
398
  backward
386
399
  end
387
- rescue Errno::ESTALE
388
- rescue Errno::ENOENT
400
+ rescue Errno::ESTALE, Errno::ENOENT
389
401
  if @reopen_deleted
390
402
  sleep @max_interval
391
403
  retry
@@ -400,20 +412,11 @@ class File
400
412
  :lines => @lines,
401
413
  :interval => @interval,
402
414
  :no_read => @no_read,
415
+ :n => @n,
403
416
  }
404
417
  $stderr.print h.inspect, "\n"
405
418
  end
406
419
  end
407
-
408
- # The rewind method is deprecated and will be removed soon, use backward
409
- # instead. At the moment rewind accidentially overwrites the IO#rewind
410
- # method, after the removal of the ol rewind mixin method, this will be no
411
- # longer the case.
412
- def rewind(*args)
413
- warn "File::Tail#rewind method is deprecated and will be removed soon, "\
414
- "use backward instead"
415
- backward *args
416
- end
417
420
  end
418
421
 
419
422
  if $0 == __FILE__
@@ -0,0 +1,10 @@
1
+ class File
2
+ module Tail
3
+ # File::Tail version
4
+ VERSION = '0.1.5'
5
+ VERSION_ARRAY = VERSION.split(/\./).map { |x| x.to_i } # :nodoc:
6
+ VERSION_MAJOR = VERSION_ARRAY[0] # :nodoc:
7
+ VERSION_MINOR = VERSION_ARRAY[1] # :nodoc:
8
+ VERSION_BUILD = VERSION_ARRAY[2] # :nodoc:
9
+ end
10
+ end
@@ -176,6 +176,8 @@ class TC_FileTail < Test::Unit::TestCase
176
176
  def test_tail_remove
177
177
  return if File::PATH_SEPARATOR == ';' # Grmpf! Windows...
178
178
  @in.backward
179
+ reopened = false
180
+ @in.after_reopen { |f| reopened = true }
179
181
  lines = []
180
182
  threads = []
181
183
  threads << appender = Thread.new do
@@ -198,6 +200,77 @@ class TC_FileTail < Test::Unit::TestCase
198
200
  end
199
201
  threads.collect { |t| t.wakeup and t.join }
200
202
  assert_equal(10, lines.size)
203
+ assert reopened
204
+ end
205
+
206
+ def test_tail_remove2
207
+ return if File::PATH_SEPARATOR == ';' # Grmpf! Windows...
208
+ @in.backward
209
+ reopened = false
210
+ @in.after_reopen { |f| reopened = true }
211
+ lines = []
212
+ threads = []
213
+ threads << appender = Thread.new do
214
+ Thread.stop
215
+ @out.close
216
+ File.unlink(@out.path)
217
+ @out = File.new(@in.path, "wb")
218
+ append(@out, 10)
219
+ sleep 1
220
+ append(@out, 10)
221
+ File.unlink(@out.path)
222
+ @out = File.new(@in.path, "wb")
223
+ append(@out, 10)
224
+ end
225
+ threads << Thread.new do
226
+ begin
227
+ timeout(2) do
228
+ @in.tail do |l|
229
+ lines << l
230
+ lines.size == 100 and appender.wakeup
231
+ end
232
+ end
233
+ rescue TimeoutError
234
+ end
235
+ end
236
+ threads.collect { |t| t.wakeup and t.join }
237
+ assert_equal(30, lines.size)
238
+ assert reopened
239
+ end
240
+
241
+ def test_tail_remove3
242
+ return if File::PATH_SEPARATOR == ';' # Grmpf! Windows...
243
+ @in.backward
244
+ reopened = false
245
+ @in.after_reopen { |f| reopened = true }
246
+ lines = []
247
+ threads = []
248
+ threads << appender = Thread.new do
249
+ Thread.stop
250
+ @out.close
251
+ File.unlink(@out.path)
252
+ @out = File.new(@in.path, "wb")
253
+ append(@out, 10)
254
+ sleep 1
255
+ append(@out, 10)
256
+ File.unlink(@out.path)
257
+ @out = File.new(@in.path, "wb")
258
+ append(@out, 10)
259
+ end
260
+ threads << Thread.new do
261
+ begin
262
+ timeout(2) do
263
+ @in.tail(15) do |l|
264
+ lines << l
265
+ lines.size == 100 and appender.wakeup
266
+ end
267
+ end
268
+ rescue TimeoutError
269
+ end
270
+ end
271
+ threads.collect { |t| t.wakeup and t.join }
272
+ assert_equal(15, lines.size)
273
+ assert reopened
201
274
  end
202
275
 
203
276
  def teardown
metadata CHANGED
@@ -1,10 +1,10 @@
1
1
  --- !ruby/object:Gem::Specification
2
- rubygems_version: 0.8.11
2
+ rubygems_version: 0.9.2
3
3
  specification_version: 1
4
4
  name: file-tail
5
5
  version: !ruby/object:Gem::Version
6
- version: 0.1.4
7
- date: 2007-02-08 00:00:00 +01:00
6
+ version: 1.0.0
7
+ date: 2007-04-01 00:00:00 +02:00
8
8
  summary: File::Tail for Ruby
9
9
  require_paths:
10
10
  - lib
@@ -25,6 +25,7 @@ required_ruby_version: !ruby/object:Gem::Version::Requirement
25
25
  platform: ruby
26
26
  signing_key:
27
27
  cert_chain:
28
+ post_install_message:
28
29
  authors:
29
30
  - Florian Frank
30
31
  files:
@@ -41,14 +42,15 @@ files:
41
42
  - examples/pager.rb
42
43
  - examples/tail.rb
43
44
  - lib/file
45
+ - lib/file/tail
44
46
  - lib/file/tail.rb
45
- test_files: &id001 []
46
-
47
+ - lib/file/tail/version.rb
48
+ test_files:
49
+ - tests/test_file-tail.rb
47
50
  rdoc_options:
48
51
  - --title
49
52
  - File::Tail
50
- - *id001
51
- - tests/test_file-tail.rb
53
+ - --line-numbers
52
54
  extra_rdoc_files: []
53
55
 
54
56
  executables: []