filewatch 0.6.1 → 0.6.2
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.
- 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: []
|