filewatch 0.6.1 → 0.6.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/filewatch/helper.rb +69 -0
- data/lib/filewatch/tail.rb +31 -38
- data/lib/filewatch/watch.rb +15 -20
- metadata +11 -11
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0e65e9502f748961f239834468650fec44803b49
|
4
|
+
data.tar.gz: d0a583f9ca8d394ab0adccda0a843e30ebcf4d40
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2a96dd9971c7bcde08e601a4e6d22c1d4fad2851b9489d79e378302fa819cc2919bb3f2bf83c5a28877d97e022f45ed6b3a53425034d4dd6eac4f04e7325f10b
|
7
|
+
data.tar.gz: 5c4eb3f52ed225b541fba0a2adfb5a869072f5473923a3de750d8e5520b4579e05b3af3822b841ed7f262f920e033ef00c2e59f3796ce42048905234fad1c161
|
@@ -0,0 +1,69 @@
|
|
1
|
+
# code downloaded from Ruby on Rails 4.2.1
|
2
|
+
# https://raw.githubusercontent.com/rails/rails/v4.2.1/activesupport/lib/active_support/core_ext/file/atomic.rb
|
3
|
+
require 'fileutils'
|
4
|
+
|
5
|
+
class File
|
6
|
+
# Write to a file atomically. Useful for situations where you don't
|
7
|
+
# want other processes or threads to see half-written files.
|
8
|
+
#
|
9
|
+
# File.atomic_write('important.file') do |file|
|
10
|
+
# file.write('hello')
|
11
|
+
# end
|
12
|
+
#
|
13
|
+
# If your temp directory is not on the same filesystem as the file you're
|
14
|
+
# trying to write, you can provide a different temporary directory.
|
15
|
+
#
|
16
|
+
# File.atomic_write('/data/something.important', '/data/tmp') do |file|
|
17
|
+
# file.write('hello')
|
18
|
+
# end
|
19
|
+
def self.atomic_write(file_name)
|
20
|
+
|
21
|
+
if File.exist?(file_name)
|
22
|
+
# Get original file permissions
|
23
|
+
old_stat = stat(file_name)
|
24
|
+
else
|
25
|
+
# If not possible, probe which are the default permissions in the
|
26
|
+
# destination directory.
|
27
|
+
old_stat = probe_stat_in(dirname(file_name))
|
28
|
+
end
|
29
|
+
|
30
|
+
mode = old_stat ? old_stat.mode : nil
|
31
|
+
|
32
|
+
# Create temporary file with identical permissions
|
33
|
+
temp_file = File.new(rand_filename(file_name), "w", mode)
|
34
|
+
temp_file.binmode
|
35
|
+
return_val = yield temp_file
|
36
|
+
temp_file.close
|
37
|
+
|
38
|
+
# Overwrite original file with temp file
|
39
|
+
File.rename(temp_file.path, file_name)
|
40
|
+
|
41
|
+
# Unable to get permissions of the original file => return
|
42
|
+
return return_val if old_stat.nil?
|
43
|
+
|
44
|
+
# Set correct uid/gid on new file
|
45
|
+
chown(old_stat.uid, old_stat.gid, file_name) if old_stat
|
46
|
+
|
47
|
+
return_val
|
48
|
+
end
|
49
|
+
|
50
|
+
# Private utility method.
|
51
|
+
def self.probe_stat_in(dir) #:nodoc:
|
52
|
+
basename = rand_filename(".permissions_check")
|
53
|
+
file_name = join(dir, basename)
|
54
|
+
FileUtils.touch(file_name)
|
55
|
+
stat(file_name)
|
56
|
+
rescue
|
57
|
+
# ...
|
58
|
+
ensure
|
59
|
+
FileUtils.rm_f(file_name) if File.exist?(file_name)
|
60
|
+
end
|
61
|
+
|
62
|
+
def self.rand_filename(prefix)
|
63
|
+
[ prefix, Thread.current.object_id, Process.pid, rand(1000000) ].join('.')
|
64
|
+
end
|
65
|
+
|
66
|
+
def self.device?(file_name)
|
67
|
+
chardev?(file_name) || blockdev?(file_name)
|
68
|
+
end
|
69
|
+
end
|
data/lib/filewatch/tail.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
require "filewatch/helper"
|
1
2
|
require "filewatch/buftok"
|
2
3
|
require "filewatch/watch"
|
3
4
|
if RbConfig::CONFIG['host_os'] =~ /mswin|mingw|cygwin/
|
@@ -103,7 +104,14 @@ module FileWatch
|
|
103
104
|
@logger.warn("unknown event type #{event} for #{path}")
|
104
105
|
end
|
105
106
|
end # @watch.subscribe
|
106
|
-
end # def
|
107
|
+
end # def subscribe
|
108
|
+
|
109
|
+
public
|
110
|
+
def sincedb_record_uid(path, stat)
|
111
|
+
inode = @watch.inode(path,stat)
|
112
|
+
@statcache[path] = inode
|
113
|
+
return inode
|
114
|
+
end # def sincedb_record_uid
|
107
115
|
|
108
116
|
private
|
109
117
|
def _open_file(path, event)
|
@@ -130,37 +138,28 @@ module FileWatch
|
|
130
138
|
end
|
131
139
|
|
132
140
|
stat = File::Stat.new(path)
|
133
|
-
|
134
|
-
if @iswindows
|
135
|
-
fileId = Winhelper.GetWindowsUniqueFileIdentifier(path)
|
136
|
-
inode = [fileId, stat.dev_major, stat.dev_minor]
|
137
|
-
else
|
138
|
-
inode = [stat.ino.to_s, stat.dev_major, stat.dev_minor]
|
139
|
-
end
|
140
|
-
|
141
|
-
@statcache[path] = inode
|
141
|
+
sincedb_record_uid = sincedb_record_uid(path, stat)
|
142
142
|
|
143
|
-
if @sincedb.member?(
|
144
|
-
last_size = @sincedb[
|
145
|
-
@logger.debug? && @logger.debug("#{path}: sincedb last value #{@sincedb[
|
143
|
+
if @sincedb.member?(sincedb_record_uid)
|
144
|
+
last_size = @sincedb[sincedb_record_uid]
|
145
|
+
@logger.debug? && @logger.debug("#{path}: sincedb last value #{@sincedb[sincedb_record_uid]}, cur size #{stat.size}")
|
146
146
|
if last_size <= stat.size
|
147
147
|
@logger.debug? && @logger.debug("#{path}: sincedb: seeking to #{last_size}")
|
148
148
|
@files[path].sysseek(last_size, IO::SEEK_SET)
|
149
149
|
else
|
150
150
|
@logger.debug? && @logger.debug("#{path}: last value size is greater than current value, starting over")
|
151
|
-
@sincedb[
|
151
|
+
@sincedb[sincedb_record_uid] = 0
|
152
152
|
end
|
153
153
|
elsif event == :create_initial && @files[path]
|
154
|
-
# TODO(sissel): Allow starting at beginning of the file.
|
155
154
|
if @opts[:start_new_files_at] == :beginning
|
156
155
|
@logger.debug? && @logger.debug("#{path}: initial create, no sincedb, seeking to beginning of file")
|
157
156
|
@files[path].sysseek(0, IO::SEEK_SET)
|
158
|
-
@sincedb[
|
157
|
+
@sincedb[sincedb_record_uid] = 0
|
159
158
|
else
|
160
159
|
# seek to end
|
161
160
|
@logger.debug? && @logger.debug("#{path}: initial create, no sincedb, seeking to end #{stat.size}")
|
162
161
|
@files[path].sysseek(stat.size, IO::SEEK_SET)
|
163
|
-
@sincedb[
|
162
|
+
@sincedb[sincedb_record_uid] = stat.size
|
164
163
|
end
|
165
164
|
else
|
166
165
|
@logger.debug? && @logger.debug("#{path}: staying at position 0, no sincedb")
|
@@ -172,7 +171,6 @@ module FileWatch
|
|
172
171
|
private
|
173
172
|
def _read_file(path, &block)
|
174
173
|
@buffers[path] ||= FileWatch::BufferedTokenizer.new(@opts[:delimiter])
|
175
|
-
|
176
174
|
changed = false
|
177
175
|
loop do
|
178
176
|
begin
|
@@ -219,9 +217,9 @@ module FileWatch
|
|
219
217
|
@logger.debug? && @logger.debug("_sincedb_open: reading from #{path}")
|
220
218
|
db.each do |line|
|
221
219
|
ino, dev_major, dev_minor, pos = line.split(" ", 4)
|
222
|
-
|
223
|
-
@logger.debug? && @logger.debug("_sincedb_open: setting #{
|
224
|
-
@sincedb[
|
220
|
+
sincedb_record_uid = [ino, dev_major.to_i, dev_minor.to_i]
|
221
|
+
@logger.debug? && @logger.debug("_sincedb_open: setting #{sincedb_record_uid.inspect} to #{pos.to_i}")
|
222
|
+
@sincedb[sincedb_record_uid] = pos.to_i
|
225
223
|
end
|
226
224
|
db.close
|
227
225
|
end # def _sincedb_open
|
@@ -229,29 +227,24 @@ module FileWatch
|
|
229
227
|
private
|
230
228
|
def _sincedb_write
|
231
229
|
path = @opts[:sincedb_path]
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
@logger.warn("_sincedb_write failed: #{tmp}: #{e}")
|
237
|
-
return
|
238
|
-
end
|
239
|
-
|
240
|
-
@sincedb.each do |inode, pos|
|
241
|
-
db.puts([inode, pos].flatten.join(" "))
|
242
|
-
end
|
243
|
-
db.close
|
244
|
-
|
245
|
-
begin
|
246
|
-
File.rename(tmp, path)
|
247
|
-
rescue => e
|
248
|
-
@logger.warn("_sincedb_write rename/sync failed: #{tmp} -> #{path}: #{e}")
|
230
|
+
if File.device?(path)
|
231
|
+
IO.write(path, serialize_sincedb, 0)
|
232
|
+
else
|
233
|
+
File.atomic_write(path) {|file| file.write(serialize_sincedb) }
|
249
234
|
end
|
250
235
|
end # def _sincedb_write
|
251
236
|
|
252
237
|
public
|
253
238
|
def quit
|
239
|
+
_sincedb_write
|
254
240
|
@watch.quit
|
255
241
|
end # def quit
|
242
|
+
|
243
|
+
private
|
244
|
+
def serialize_sincedb
|
245
|
+
@sincedb.map do |inode, pos|
|
246
|
+
[inode, pos].flatten.join(" ")
|
247
|
+
end.join("\n") + "\n"
|
248
|
+
end
|
256
249
|
end # class Tail
|
257
250
|
end # module FileWatch
|
data/lib/filewatch/watch.rb
CHANGED
@@ -39,7 +39,18 @@ module FileWatch
|
|
39
39
|
end
|
40
40
|
|
41
41
|
return true
|
42
|
-
end # def
|
42
|
+
end # def watch
|
43
|
+
|
44
|
+
public
|
45
|
+
def inode(path,stat)
|
46
|
+
if @iswindows
|
47
|
+
fileId = Winhelper.GetWindowsUniqueFileIdentifier(path)
|
48
|
+
inode = [fileId, stat.dev_major, stat.dev_minor]
|
49
|
+
else
|
50
|
+
inode = [stat.ino.to_s, stat.dev_major, stat.dev_minor]
|
51
|
+
end
|
52
|
+
return inode
|
53
|
+
end
|
43
54
|
|
44
55
|
# Calls &block with params [event_type, path]
|
45
56
|
# event_type can be one of:
|
@@ -72,13 +83,7 @@ module FileWatch
|
|
72
83
|
next
|
73
84
|
end
|
74
85
|
|
75
|
-
|
76
|
-
fileId = Winhelper.GetWindowsUniqueFileIdentifier(path)
|
77
|
-
inode = [fileId, stat.dev_major, stat.dev_minor]
|
78
|
-
else
|
79
|
-
inode = [stat.ino.to_s, stat.dev_major, stat.dev_minor]
|
80
|
-
end
|
81
|
-
|
86
|
+
inode = inode(path,stat)
|
82
87
|
if inode != @files[path][:inode]
|
83
88
|
@logger.debug? && @logger.debug("#{path}: old inode was #{@files[path][:inode].inspect}, new is #{inode.inspect}")
|
84
89
|
yield(:delete, path)
|
@@ -149,20 +154,10 @@ module FileWatch
|
|
149
154
|
stat = File::Stat.new(file)
|
150
155
|
@files[file] = {
|
151
156
|
:size => 0,
|
152
|
-
:inode =>
|
157
|
+
:inode => inode(file,stat),
|
153
158
|
:create_sent => false,
|
159
|
+
:initial => initial
|
154
160
|
}
|
155
|
-
|
156
|
-
if @iswindows
|
157
|
-
fileId = Winhelper.GetWindowsUniqueFileIdentifier(file)
|
158
|
-
@files[file][:inode] = [fileId, stat.dev_major, stat.dev_minor]
|
159
|
-
else
|
160
|
-
@files[file][:inode] = [stat.ino.to_s, stat.dev_major, stat.dev_minor]
|
161
|
-
end
|
162
|
-
|
163
|
-
if initial
|
164
|
-
@files[file][:initial] = true
|
165
|
-
end
|
166
161
|
end
|
167
162
|
end # def _discover_file
|
168
163
|
|
metadata
CHANGED
@@ -1,18 +1,17 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: filewatch
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.6.
|
4
|
+
version: 0.6.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jordan Sissel
|
8
8
|
- Pete Fritchman
|
9
|
-
autorequire:
|
9
|
+
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2015-
|
12
|
+
date: 2015-04-14 00:00:00.000000000 Z
|
13
13
|
dependencies: []
|
14
|
-
description: Watch files and directories in ruby. Also supports tailing and glob file
|
15
|
-
patterns.
|
14
|
+
description: Watch files and directories in ruby. Also supports tailing and glob file patterns.
|
16
15
|
email:
|
17
16
|
- jls@semicomplete.com
|
18
17
|
- petef@databits.net
|
@@ -24,6 +23,7 @@ files:
|
|
24
23
|
- bin/globtail
|
25
24
|
- lib/JRubyFileExtension.jar
|
26
25
|
- lib/filewatch/buftok.rb
|
26
|
+
- lib/filewatch/helper.rb
|
27
27
|
- lib/filewatch/tail.rb
|
28
28
|
- lib/filewatch/watch.rb
|
29
29
|
- lib/filewatch/winhelper.rb
|
@@ -53,25 +53,25 @@ files:
|
|
53
53
|
homepage: https://github.com/jordansissel/ruby-filewatch
|
54
54
|
licenses: []
|
55
55
|
metadata: {}
|
56
|
-
post_install_message:
|
56
|
+
post_install_message:
|
57
57
|
rdoc_options: []
|
58
58
|
require_paths:
|
59
59
|
- lib
|
60
60
|
- lib
|
61
61
|
required_ruby_version: !ruby/object:Gem::Requirement
|
62
62
|
requirements:
|
63
|
-
- -
|
63
|
+
- - '>='
|
64
64
|
- !ruby/object:Gem::Version
|
65
65
|
version: '0'
|
66
66
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
67
67
|
requirements:
|
68
|
-
- -
|
68
|
+
- - '>='
|
69
69
|
- !ruby/object:Gem::Version
|
70
70
|
version: '0'
|
71
71
|
requirements: []
|
72
|
-
rubyforge_project:
|
73
|
-
rubygems_version: 2.
|
74
|
-
signing_key:
|
72
|
+
rubyforge_project:
|
73
|
+
rubygems_version: 2.2.2
|
74
|
+
signing_key:
|
75
75
|
specification_version: 4
|
76
76
|
summary: filewatch - file watching for ruby
|
77
77
|
test_files: []
|