file-tail-1.0.12/ 0000755 0000041 0000041 00000000000 12055510146 013470 5 ustar www-data www-data file-tail-1.0.12/.travis.yml 0000644 0000041 0000041 00000000250 12055510146 015576 0 ustar www-data www-data rvm:
- 1.8.7
- 1.9.2
- 1.9.3
- ruby-head
- ree
- rbx-18mode
- rbx-19mode
- jruby-18mode
- jruby-19mode
matrix:
allow_failures:
- rvm: ruby-head
file-tail-1.0.12/examples/ 0000755 0000041 0000041 00000000000 12055510146 015306 5 ustar www-data www-data file-tail-1.0.12/examples/pager.rb 0000755 0000041 0000041 00000000643 12055510146 016737 0 ustar www-data www-data #!/usr/bin/env ruby
# A poor man's pager... :)
require 'file/tail'
filename = ARGV.shift or fail "Usage: #$0 filename [height]"
height = (ARGV.shift || ENV['LINES'] || 23).to_i - 1
File::Tail::Logfile.open(filename, :break_if_eof => true) do |log|
begin
log.tail(height) { |line| puts line }
print "Press return key to continue!" ; gets
print ""
redo
rescue File::Tail::BreakException
end
end
file-tail-1.0.12/examples/tail.rb 0000755 0000041 0000041 00000000347 12055510146 016573 0 ustar www-data www-data #!/usr/bin/env ruby
require 'file/tail'
filename = ARGV.pop or fail "Usage: #$0 number filename"
number = (ARGV.pop || 0).to_i.abs
File::Tail::Logfile.open(filename) do |log|
log.backward(number).tail { |line| puts line }
end
file-tail-1.0.12/tests/ 0000755 0000041 0000041 00000000000 12055510146 014632 5 ustar www-data www-data file-tail-1.0.12/tests/test_helper.rb 0000644 0000041 0000041 00000000250 12055510146 017472 0 ustar www-data www-data if ENV['START_SIMPLECOV'].to_i == 1
require 'simplecov'
SimpleCov.start do
add_filter "#{File.basename(File.dirname(__FILE__))}/"
end
end
require 'test/unit'
file-tail-1.0.12/tests/file_tail_test.rb 0000644 0000041 0000041 00000020070 12055510146 020145 0 ustar www-data www-data #!/usr/bin/env ruby
require 'test_helper'
require 'file/tail'
require 'timeout'
require 'thread'
Thread.abort_on_exception = true
class FileTailTest < Test::Unit::TestCase
include File::Tail
def setup
@out = File.new("test.#$$", "wb")
append(@out, 100)
@in = File.new(@out.path, "rb")
@in.extend(File::Tail)
@in.interval = 0.4
@in.max_interval = 0.8
@in.reopen_deleted = true # is default
@in.reopen_suspicious = true # is default
@in.suspicious_interval = 60
end
def test_forward
[ 0, 1, 2, 10, 100 ].each do |lines|
@in.forward(lines)
assert_equal(100 - lines, count(@in))
end
@in.forward(101)
assert_equal(0, count(@in))
end
def test_backward
[ 0, 1, 2, 10, 100 ].each do |lines|
@in.backward(lines)
assert_equal(lines, count(@in))
end
@in.backward(101)
assert_equal(100, count(@in))
end
def test_backward_small_buffer
[ 0, 1, 2, 10, 100 ].each do |lines|
@in.backward(lines, 100)
assert_equal(lines, count(@in))
end
@in.backward(101, 100)
assert_equal(100, count(@in))
end
def test_backward_small_buffer2
@in.default_bufsize = 100
[ 0, 1, 2, 10, 100 ].each do |lines|
@in.backward(lines)
assert_equal(lines, count(@in))
end
@in.backward(101)
assert_equal(100, count(@in))
end
def test_tail_with_block_without_n
timeout(10) do
lines = []
@in.backward(1)
assert_raises(TimeoutError) do
timeout(1) { @in.tail { |l| lines << l } }
end
assert_equal(1, lines.size)
#
lines = []
@in.backward(10)
assert_raises(TimeoutError) do
timeout(1) { @in.tail { |l| lines << l } }
end
assert_equal(10, lines.size)
#
lines = []
@in.backward(100)
assert_raises(TimeoutError) do
timeout(1) { @in.tail { |l| lines << l } }
end
assert_equal(100, lines.size)
#
lines = []
@in.backward(101)
assert_raises(TimeoutError) do
timeout(1) { @in.tail { |l| lines << l } }
end
end
end
def test_tail_with_block_with_n
timeout(10) do
@in.backward(1)
lines = []
timeout(1) { @in.tail(0) { |l| lines << l } }
assert_equal(0, lines.size)
#
@in.backward(1)
lines = []
timeout(1) { @in.tail(1) { |l| lines << l } }
assert_equal(1, lines.size)
#
@in.backward(10)
lines = []
timeout(1) { @in.tail(10) { |l| lines << l } }
assert_equal(10, lines.size)
#
@in.backward(100)
lines = []
@in.backward(1)
assert_raises(TimeoutError) do
timeout(1) { @in.tail(2) { |l| lines << l } }
end
assert_equal(1, lines.size)
#
end
end
def test_tail_without_block_with_n
timeout(10) do
@in.backward(1)
lines = []
timeout(1) { lines += @in.tail(0) }
assert_equal(0, lines.size)
#
@in.backward(1)
lines = []
timeout(1) { lines += @in.tail(1) }
assert_equal(1, lines.size)
#
@in.backward(10)
lines = []
timeout(1) { lines += @in.tail(10) }
assert_equal(10, lines.size)
#
@in.backward(100)
lines = []
@in.backward(1)
assert_raises(TimeoutError) do
timeout(1) { lines += @in.tail(2) }
end
assert_equal(0, lines.size)
end
end
def test_tail_withappend
@in.backward
lines = []
logger = Thread.new do
begin
timeout(1) { @in.tail { |l| lines << l } }
rescue TimeoutError
end
end
appender = Thread.new { append(@out, 10) }
appender.join
logger.join
assert_equal(10, lines.size)
end
def test_tail_truncated
@in.backward
lines = []
logger = Thread.new do
begin
timeout(10) do
@in.tail do |l|
lines << l
end
end
rescue TimeoutError
end
end
appender = Thread.new do
until logger.stop?
sleep 0.1
end
@out.close
File.truncate(@out.path, 0)
@out = File.new(@in.path, "ab")
append(@out, 10)
end
appender.join
logger.join
assert_equal(10, lines.size)
end
def test_tail_remove
return if File::PATH_SEPARATOR == ';' # Grmpf! Windows...
@in.backward
reopened = false
@in.after_reopen { |f| reopened = true }
lines = []
logger = Thread.new do
begin
timeout(2) do
@in.tail do |l|
lines << l
end
end
rescue TimeoutError
end
end
appender = Thread.new do
until logger.stop?
sleep 0.1
end
@out.close
File.unlink(@out.path)
@out = File.new(@in.path, "wb")
append(@out, 10)
end
appender.join
logger.join
assert_equal(10, lines.size)
assert reopened
end
def test_tail_remove2
return if File::PATH_SEPARATOR == ';' # Grmpf! Windows...
@in.backward
reopened = false
@in.after_reopen { |f| reopened = true }
lines = []
logger = Thread.new do
begin
timeout(2) do
@in.tail do |l|
lines << l
end
end
rescue TimeoutError
end
end
appender = Thread.new do
until logger.stop?
sleep 0.1
end
@out.close
File.unlink(@out.path)
@out = File.new(@in.path, "wb")
append(@out, 10)
sleep 1
append(@out, 10)
File.unlink(@out.path)
@out = File.new(@in.path, "wb")
append(@out, 10)
end
appender.join
logger.join
assert_equal(30, lines.size)
assert reopened
end
def test_tail_remove3
return if File::PATH_SEPARATOR == ';' # Grmpf! Windows...
@in.backward
reopened = false
@in.after_reopen { |f| reopened = true }
lines = []
logger = Thread.new do
begin
timeout(2) do
@in.tail(15) do |l|
lines << l
end
end
rescue TimeoutError
end
end
appender = Thread.new do
until logger.stop?
sleep 0.1
end
@out.close
File.unlink(@out.path)
@out = File.new(@in.path, "wb")
append(@out, 10)
sleep 1
append(@out, 10)
File.unlink(@out.path)
@out = File.new(@in.path, "wb")
append(@out, 10)
end
appender.join
logger.join
assert_equal(15, lines.size)
assert reopened
end
def test_tail_change
return if File::PATH_SEPARATOR == ';' # Grmpf! Windows...
@in.forward
reopened = false
assert_equal 0, @in.lineno
@in.after_reopen { |f| reopened = true }
lines = []
logger = Thread.new do
begin
timeout(2) do
@in.tail(110) do |l|
lines << l
end
end
rescue TimeoutError
end
end
appender = Thread.new do
until logger.stop?
sleep 0.1
end
@out.close
File.unlink(@out.path)
@out = File.new(@in.path, "wb")
append(@out, 10)
end
appender.join
logger.join
assert_equal(110, lines.size)
assert reopened
assert_equal 10, @in.lineno
end
def test_tail_change2
return if File::PATH_SEPARATOR == ';' # Grmpf! Windows...
@in.forward
reopened = false
assert_equal 0, @in.lineno
@in.after_reopen { |f| reopened = true }
lines = []
logger = Thread.new do
begin
timeout(2) do
@in.tail(110) do |l|
lines << l
end
end
rescue TimeoutError
end
end
appender = Thread.new do
until logger.stop?
sleep 0.1
end
@out.truncate 0
@out.close
@out = File.new(@in.path, "wb")
append(@out, 10)
end
appender.join
logger.join
assert_equal(110, lines.size)
assert reopened
assert_equal 10, @in.lineno
end
def teardown
@in.close
@out.close
File.unlink(@out.path)
end
private
def count(file)
n = 0
until file.eof?
file.readline
n += 1
end
return n
end
def append(file, n, size = 70)
(1..n).each { |x| file << "#{x} #{"A" * size}\n" }
file.flush
end
end
file-tail-1.0.12/tests/file_tail_group_test.rb 0000644 0000041 0000041 00000003565 12055510146 021373 0 ustar www-data www-data #!/usr/bin/env ruby
require 'test_helper'
require 'file/tail'
require 'timeout'
require 'thread'
require 'tempfile'
Thread.abort_on_exception = true
class FileTailGroupTest < Test::Unit::TestCase
include File::Tail
def test_create_group
t, = make_file
g = Group[t]
assert_equal t.path, g.each_tailer.first.file.path
assert_equal t.path, g.each_file.first.path
end
def test_stop_group
t, = make_file
g = Group[t]
assert_equal t.path, g.each_tailer.first.file.path
assert_equal t.path, g.each_file.first.path
g.stop
assert_nil g.each_file.first
end
def test_add_file_to_group
g = Group.new
t, = make_file
g.add_file t
assert_equal t.path, g.each_tailer.first.file.path
assert_equal t.path, g.each_file.first.path
end
def test_add_filename_to_group
g = Group.new
t, name = make_file
t.close
g.add_filename name
assert_equal name, g.each_tailer.first.file.path
assert_equal t.path, g.each_file.first.path
end
def test_add_generic_to_group
g = Group.new
t1, n1 = make_file
t1.close
t2, n1 = make_file
g << n1
g << t2
assert g.each_tailer.any? { |t| t.file.path == n1 }
assert g.each_tailer.any? { |t| t.file.path == t2.path }
assert g.each_file.any? { |t| t.path == n1 }
assert g.each_file.any? { |t| t.path == t2.path }
end
def test_tail_multiple_files
t1, = make_file
t1.max_interval = 0.1
t2, = make_file
t2.max_interval = 0.1
g = Group[t1, t2]
q = Queue.new
t = Thread.new do
g.tail { |l| q << l }
end
t1.puts "foo"
assert_equal "foo\n", q.pop
t2.puts "bar"
assert_equal "bar\n", q.pop
ensure
t and t.exit
end
private
def make_file
name = File.expand_path(File.join(Dir.tmpdir, "tmp.#$$"))
file = File.open(name, 'w+')
file.extend File::Tail
return file, name
end
end
file-tail-1.0.12/README.rdoc 0000644 0000041 0000041 00000003570 12055510146 015303 0 ustar www-data www-data = File::Tail for Ruby
== Description
This is a small ruby library that allows it to "tail" files in Ruby, including
following a file, that still is growing like the unix command 'tail -f' can.
== Download
The latest version of File::Tail (file-tail) can be found at
http://www.ping.de/~flori
Online Documentation should be located at
http://flori.github.com/file-tail
== Installation
To install file-tail via its gem type:
# gem install file-tail
To install from the source repository, just type into the command line as root:
# rake install
== Usage
File::Tail is a module in the File class. A lightweight class interface for
logfiles can be seen under File::Tail::Logfile.
Direct extension of File objects with File::Tail works like that:
File.open(filename) do |log|
log.extend(File::Tail)
log.interval = 10
log.backward(10)
log.tail { |line| puts line }
end
It's also possible to mix File::Tail in your own File classes
(see also File::Tail::Logfile):
class MyFile < File
include File::Tail
end
log = MyFile.new("myfile")
log.interval = 10
log.backward(10)
log.tail { |line| print line }
The forward/backward method returns self, so it's possible to chain
methods together like that:
log.backward(10).tail { |line| puts line }
A command line utility named rtail, that uses File::Tail is provided as well.
== Documentation
To create the documentation of this module, type
$ rake doc
and the API documentation is generated.
In the examples direcotry is a small example of tail and
pager program that use this module. You also may want look
at the end of file/tail.rb for a little example.
== Author
Florian Frank mailto:flori@ping.de
== License
This is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License Version 2 as published by
the Free Software Foundation: http://www.gnu.org/copyleft/gpl.html
file-tail-1.0.12/Rakefile 0000644 0000041 0000041 00000001772 12055510146 015144 0 ustar www-data www-data # vim: set filetype=ruby et sw=2 ts=2:
require 'gem_hadar'
GemHadar do
name 'file-tail'
path_name 'file/tail'
author 'Florian Frank'
email 'flori@ping.de'
homepage "http://github.com/flori/#{name}"
summary "#{path_name.camelize} for Ruby"
description 'Library to tail files in Ruby'
test_dir 'tests'
ignore '.*.sw[pon]', 'pkg', 'Gemfile.lock', 'coverage', '*.rbc', '.rbx'
readme 'README.rdoc'
dependency 'tins', '~>0.5'
development_dependency 'test-unit', '~>2.4.0'
install_library do
cd 'lib' do
libdir = CONFIG["sitelibdir"]
dest = File.join(libdir, 'file')
mkdir_p(dest)
dest = File.join(libdir, path_name)
install(path_name + '.rb', dest + '.rb', :verbose => true)
mkdir_p(dest)
for file in Dir[File.join(path_name, '*.rb')]
install(file, dest, :verbose => true)
end
end
bindir = CONFIG["bindir"]
install('bin/rtail', bindir, :verbose => true, :mode => 0755)
end
end
file-tail-1.0.12/VERSION 0000644 0000041 0000041 00000000007 12055510146 014535 0 ustar www-data www-data 1.0.12
file-tail-1.0.12/bin/ 0000755 0000041 0000041 00000000000 12055510146 014240 5 ustar www-data www-data file-tail-1.0.12/bin/rtail 0000755 0000041 0000041 00000002523 12055510146 015303 0 ustar www-data www-data #!/usr/bin/env ruby
require 'file/tail'
require 'tins/go'
include Tins::GO
require 'thread'
Thread.abort_on_exception = true
$opt = go 'n:m:Mh'
if $opt['h']
puts <