file-digests 0.0.12 → 0.0.17

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 5b7e14619d7b7a27805bd7cf3a27240df66b3e6144063d356f04912df21be688
4
- data.tar.gz: 0ee51f824ffb7b159ef4f147aaa46e239f367388e3531440918fda3756340002
3
+ metadata.gz: 27ef5c07b544bb7e63a8b9ca9d8b99d0b46588b45311ef940d7431691178b99c
4
+ data.tar.gz: b1febf1fbdabab014eca65a86e3beee4cfaf4478ead18a5da071b045ae0ab56a
5
5
  SHA512:
6
- metadata.gz: 80debef1838828adc8eefcc1c16f8a4467d4b7f871475d26af80a07bace18541673ae331260908a66e4942dd396d997a383dd9a3a4a1e73a5ff9fa253b87fe94
7
- data.tar.gz: f1df92ff7323f09673dcb81cdaf33511cf4cdd0ffbc78b1c84955885bad6408c693e6abca1b4d39ea9bbfe4ea70d1cf82d62d91c6c65c130c96422c77b8f8a17
6
+ metadata.gz: f4d0db5b5ca2a29adaac1fa9aaefd276977f39d0c6e7e17e5432586d63a91a5bb20bd4af8c955e4e5c625460102ae1431b33947e5c40cc9351c5bb858f28974b
7
+ data.tar.gz: 3dc1ec4ac2224a84d1cc914b81314ccfba5580a11ca179ac9b4ca9201a599f57a52edb997af8adc369861124a733d1030f5dcb2a234dbf3c10a68b03690a5b3a
@@ -1,8 +1,5 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
- QUIET = (ENV["QUIET"] == "true")
4
- TEST_ONLY = (ENV["TEST_ONLY"] == "true")
5
-
6
3
  require 'file-digests'
7
4
 
8
5
  FileDigests.perform_check
@@ -1,7 +1,6 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
- QUIET = (ENV["QUIET"] == "true")
4
- TEST_ONLY = true
3
+ ENV["TEST_ONLY"] = "true"
5
4
 
6
5
  require 'file-digests'
7
6
 
@@ -1,4 +1,3 @@
1
-
2
1
  require 'date'
3
2
  require 'set'
4
3
  require 'digest'
@@ -8,34 +7,20 @@ require 'sqlite3'
8
7
 
9
8
  module FileDigests
10
9
 
11
- def self.ensure_dir_exists path
12
- if File.exist?(path)
13
- unless File.directory?(path)
14
- raise "#{path} is not a directory"
15
- end
16
- else
17
- FileUtils.mkdir_p path
18
- end
19
- end
20
-
21
- def self.measure_time
22
- start = Process.clock_gettime(Process::CLOCK_MONOTONIC)
23
- yield
24
- elapsed = (Process.clock_gettime(Process::CLOCK_MONOTONIC) - start).to_i
25
- puts "Elapsed time: #{elapsed / 3600}h #{(elapsed % 3600) / 60}m #{elapsed % 60}s" unless QUIET
26
- end
27
-
28
- def self.patch_path_string path
29
- Gem.win_platform? ? path.gsub(/\\/, '/') : path
30
- end
31
-
32
10
  def self.perform_check
33
- checker = Checker.new ARGV[0], ARGV[1]
11
+ options = {
12
+ auto: (ENV["AUTO"] == "true"),
13
+ quiet: (ENV["QUIET"] == "true"),
14
+ test_only: (ENV["TEST_ONLY"] == "true")
15
+ }
16
+ checker = Checker.new ARGV[0], ARGV[1], options
34
17
  checker.perform_check
35
18
  end
36
19
 
37
20
  class DigestDatabase
38
- def initialize path
21
+ def initialize path, options = {}
22
+ @options = options
23
+
39
24
  @db = SQLite3::Database.new path.to_s
40
25
  @db.results_as_hash = true
41
26
 
@@ -76,8 +61,8 @@ module FileDigests
76
61
 
77
62
  if found['digest'] == digest
78
63
  counters[:good] += 1
79
- # puts "GOOD: #{file_path}" unless QUIET
80
- unless TEST_ONLY
64
+ # puts "GOOD: #{file_path}" unless @options[:quiet]
65
+ unless @options[:test_only]
81
66
  if found['mtime'] == mtime
82
67
  touch_digest_check_time found['id']
83
68
  else
@@ -90,47 +75,50 @@ module FileDigests
90
75
  STDERR.puts "LIKELY DAMAGED: #{file_path}"
91
76
  else
92
77
  counters[:updated] += 1
93
- puts "UPDATED: #{file_path}" unless QUIET
94
- unless TEST_ONLY
78
+ puts "UPDATED: #{file_path}" unless @options[:quiet]
79
+ unless @options[:test_only]
95
80
  update_mtime_and_digest mtime, digest, found['id']
96
81
  end
97
82
  end
98
83
  end
99
84
  else
100
85
  counters[:new] += 1
101
- puts "NEW: #{file_path}" unless QUIET
102
- unless TEST_ONLY
86
+ puts "NEW: #{file_path}" unless @options[:quiet]
87
+ unless @options[:test_only]
103
88
  @new_files[file_path] = digest
104
89
  insert file_path, mtime, digest
105
90
  end
106
91
  end
107
92
  end
108
93
 
109
- def process_missing_files counters
94
+ def track_renames counters
110
95
  @missing_files.delete_if do |filename, digest|
111
96
  if @new_files.value?(digest)
112
97
  counters[:renamed] += 1
113
- unless TEST_ONLY
98
+ unless @options[:test_only]
114
99
  delete_by_filename filename
115
100
  end
116
101
  true
117
102
  end
118
103
  end
104
+ counters[:missing] = @missing_files.length
105
+ end
119
106
 
120
- if (counters[:missing] = @missing_files.length) > 0
121
- puts "\nMISSING FILES:"
122
- @missing_files.sort.to_h.each do |filename, digest|
123
- puts filename
124
- end
125
- unless TEST_ONLY
126
- puts "Remove missing files from the database (y/n)?"
127
- if STDIN.gets.strip.downcase == "y"
128
- @db.transaction do
129
- @missing_files.each do |filename, digest|
130
- delete_by_filename filename
131
- end
132
- end
133
- end
107
+ def any_missing_files?
108
+ @missing_files.length > 0
109
+ end
110
+
111
+ def print_missing_files
112
+ puts "\nMISSING FILES:"
113
+ @missing_files.sort.to_h.each do |filename, digest|
114
+ puts filename
115
+ end
116
+ end
117
+
118
+ def remove_missing_files
119
+ @db.transaction do
120
+ @missing_files.each do |filename, digest|
121
+ delete_by_filename filename
134
122
  end
135
123
  end
136
124
  end
@@ -151,40 +139,53 @@ module FileDigests
151
139
  end
152
140
 
153
141
  class Checker
154
- def initialize files_path, digest_database_path
155
- @files_path = Pathname.new(FileDigests::patch_path_string(files_path || ".")).cleanpath
142
+ def initialize files_path, digest_database_path, options = {}
143
+ @options = options
144
+ @files_path = cleanup_path(files_path || ".")
156
145
  @prefix_to_remove = @files_path.to_s + '/'
157
146
 
158
147
  raise "Files path must be a readable directory" unless (File.directory?(@files_path) && File.readable?(@files_path))
159
148
 
160
149
  @digest_database_path = if digest_database_path
161
- Pathname.new(FileDigests::patch_path_string(digest_database_path)).cleanpath
150
+ cleanup_path(digest_database_path)
162
151
  else
163
152
  @files_path + '.file-digests.sqlite'
164
153
  end
165
154
 
155
+ if File.directory?(@digest_database_path)
156
+ @digest_database_path = @digest_database_path + '.file-digests.sqlite'
157
+ end
158
+
166
159
  if @files_path == @digest_database_path.dirname
167
160
  @skip_file_digests_sqlite = true
168
161
  end
169
162
 
170
- FileDigests::ensure_dir_exists @digest_database_path.dirname
163
+ ensure_dir_exists @digest_database_path.dirname
171
164
 
165
+ # Please do not use this flag, support for sha512 is here for backward compatibility, and one day it will be removed.
172
166
  if File.exist?(@digest_database_path.dirname + '.file-digests.sha512')
173
167
  @use_sha512 = true
174
168
  end
175
169
 
176
- @digest_database = DigestDatabase.new @digest_database_path
170
+ @digest_database = DigestDatabase.new @digest_database_path, @options
177
171
  @counters = {good: 0, updated: 0, new: 0, missing: 0, renamed: 0, likely_damaged: 0, exceptions: 0}
178
172
  end
179
173
 
180
174
  def perform_check
181
- FileDigests::measure_time do
175
+ measure_time do
182
176
  walk_files do |filename|
183
177
  process_file filename
184
178
  end
185
179
  end
186
180
 
187
- @digest_database.process_missing_files @counters
181
+ @digest_database.track_renames @counters
182
+
183
+ if @digest_database.any_missing_files?
184
+ @digest_database.print_missing_files
185
+ if !@options[:test_only] && (@options[:auto] || confirm("Remove missing files from the database"))
186
+ @digest_database.remove_missing_files
187
+ end
188
+ end
188
189
 
189
190
  if @counters[:likely_damaged] > 0 || @counters[:exceptions] > 0
190
191
  STDERR.puts "ERRORS WERE OCCURRED"
@@ -193,9 +194,13 @@ module FileDigests
193
194
  puts @counters.inspect
194
195
  end
195
196
 
196
- def walk_files
197
- Dir.glob(@files_path + '**' + '*', File::FNM_DOTMATCH) do |filename|
198
- yield filename
197
+ private
198
+
199
+
200
+ def confirm text
201
+ if STDIN.tty? && STDOUT.tty?
202
+ puts "#{text} (y/n)?"
203
+ STDIN.gets.strip.downcase == "y"
199
204
  end
200
205
  end
201
206
 
@@ -229,7 +234,31 @@ module FileDigests
229
234
  )
230
235
  rescue => exception
231
236
  @counters[:exceptions] += 1
232
- STDERR.puts "EXCEPTION: #{filename}: #{exception.message}"
237
+ STDERR.puts "EXCEPTION: #{filename.encode('utf-8', universal_newline: true)}: #{exception.message}"
238
+ end
239
+
240
+ def patch_path_string path
241
+ Gem.win_platform? ? path.gsub(/\\/, '/') : path
242
+ end
243
+
244
+ def cleanup_path path
245
+ Pathname.new(patch_path_string(path)).cleanpath
246
+ end
247
+
248
+ def ensure_dir_exists path
249
+ if File.exist?(path)
250
+ unless File.directory?(path)
251
+ raise "#{path} is not a directory"
252
+ end
253
+ else
254
+ FileUtils.mkdir_p path
255
+ end
256
+ end
257
+
258
+ def walk_files
259
+ Dir.glob(@files_path + '**' + '*', File::FNM_DOTMATCH) do |filename|
260
+ yield filename
261
+ end
233
262
  end
234
263
 
235
264
  def get_file_digest filename
@@ -243,5 +272,12 @@ module FileDigests
243
272
  end
244
273
  end
245
274
 
275
+ def measure_time
276
+ start = Process.clock_gettime(Process::CLOCK_MONOTONIC)
277
+ yield
278
+ elapsed = (Process.clock_gettime(Process::CLOCK_MONOTONIC) - start).to_i
279
+ puts "Elapsed time: #{elapsed / 3600}h #{(elapsed % 3600) / 60}m #{elapsed % 60}s" unless @options[:quiet]
280
+ end
281
+
246
282
  end
247
283
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: file-digests
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.12
4
+ version: 0.0.17
5
5
  platform: ruby
6
6
  authors:
7
7
  - Stanislav Senotrusov