file-digests 0.0.13 → 0.0.18

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b587b7a9fd95e7a09b488041e0e80ee91e95f685b32b159f80c0bf494eabc77b
4
- data.tar.gz: 8b261afd681d6d6213b03c7dc65391e7533f04896e4e13f3c1bd73ddebca74a7
3
+ metadata.gz: d69e75a52c05cbc2caf912491be9fbaaadb5136a2dfc723920a9010d3e4c2592
4
+ data.tar.gz: f90deae82f2581d301d1cb7ba7c730e684b24f5c9582d6deb2581b9f2e6fa557
5
5
  SHA512:
6
- metadata.gz: aa76de6ec0bae260aa6bf289ead5a1443769f7823ae8886c2730b1235fbc9721eb39b8be56167ce654e41f6df5c5e6a10c8f1c08c03282cb32d580c09749e398
7
- data.tar.gz: a6ecefb33487aa3738b42922004d4b671b39172448a0af37d183ad6f41cf4c99be80083390bf28d695ba01badf2940a5e89cf4bf9220eca8ac9b00cba3faaa24
6
+ metadata.gz: 5ad20e936d21d42f56ed20250728eb0b7c2b9a034877e764f528c6e297853bb7724d6780a56b7c0f11a3df975c1d51fed04852ddb3f3ff9848f4c546167902e8
7
+ data.tar.gz: 27f86166310f420ac5858fa86c0233af666bbb2af40f53501a9f8e02205a3753151db5cfd6777558bbf0040e2472f9bc296d9382afebb8dd45f65fb981fc173b
@@ -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
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ ENV["AUTO"] = "true"
4
+
5
+ require 'file-digests'
6
+
7
+ 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,14 +139,15 @@ 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
@@ -171,24 +160,32 @@ module FileDigests
171
160
  @skip_file_digests_sqlite = true
172
161
  end
173
162
 
174
- FileDigests::ensure_dir_exists @digest_database_path.dirname
163
+ ensure_dir_exists @digest_database_path.dirname
175
164
 
165
+ # Please do not use this flag, support for sha512 is here for backward compatibility, and one day it will be removed.
176
166
  if File.exist?(@digest_database_path.dirname + '.file-digests.sha512')
177
167
  @use_sha512 = true
178
168
  end
179
169
 
180
- @digest_database = DigestDatabase.new @digest_database_path
170
+ @digest_database = DigestDatabase.new @digest_database_path, @options
181
171
  @counters = {good: 0, updated: 0, new: 0, missing: 0, renamed: 0, likely_damaged: 0, exceptions: 0}
182
172
  end
183
173
 
184
174
  def perform_check
185
- FileDigests::measure_time do
175
+ measure_time do
186
176
  walk_files do |filename|
187
177
  process_file filename
188
178
  end
189
179
  end
190
180
 
191
- @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
192
189
 
193
190
  if @counters[:likely_damaged] > 0 || @counters[:exceptions] > 0
194
191
  STDERR.puts "ERRORS WERE OCCURRED"
@@ -197,9 +194,13 @@ module FileDigests
197
194
  puts @counters.inspect
198
195
  end
199
196
 
200
- def walk_files
201
- Dir.glob(@files_path + '**' + '*', File::FNM_DOTMATCH) do |filename|
202
- 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"
203
204
  end
204
205
  end
205
206
 
@@ -233,7 +234,31 @@ module FileDigests
233
234
  )
234
235
  rescue => exception
235
236
  @counters[:exceptions] += 1
236
- 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
237
262
  end
238
263
 
239
264
  def get_file_digest filename
@@ -247,5 +272,12 @@ module FileDigests
247
272
  end
248
273
  end
249
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
+
250
282
  end
251
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.13
4
+ version: 0.0.18
5
5
  platform: ruby
6
6
  authors:
7
7
  - Stanislav Senotrusov
@@ -28,11 +28,13 @@ description: Calculate file digests and check for the possible file corruption
28
28
  email: stan@senotrusov.com
29
29
  executables:
30
30
  - file-digests
31
+ - file-digests-auto
31
32
  - file-digests-test
32
33
  extensions: []
33
34
  extra_rdoc_files: []
34
35
  files:
35
36
  - bin/file-digests
37
+ - bin/file-digests-auto
36
38
  - bin/file-digests-test
37
39
  - lib/file-digests.rb
38
40
  homepage: https://github.com/senotrusov/file-digests