file-digests 0.0.31 → 0.0.36

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.
Files changed (4) hide show
  1. checksums.yaml +4 -4
  2. data/bin/file-digests +14 -0
  3. data/lib/file-digests.rb +164 -99
  4. metadata +2 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c7a7259116dbf913b55651133e3bcb5e5ed545bd42e9bb63b1e5f83fb7b98a57
4
- data.tar.gz: 17915ee54fceff38c52d451db21648b15fb0a3ef4c595df7736b7e077dbbb10e
3
+ metadata.gz: 624f7ec80a0cb15be2bc07a3dd592c33c7a178c22fb7f59ef326760d17cc564f
4
+ data.tar.gz: 92bb88c58bc152ad01649b0688861ea16af6801d2d6625c238b96e9ff00aaed4
5
5
  SHA512:
6
- metadata.gz: d186110615604c8a833f213cf5dee0f41e19992bc34b335f59e8126ad4dc5995a5601ec9ac0559b7fa930b58c9e8ee11a258a5392dd4f4433c21765ee1e99b1b
7
- data.tar.gz: ed21957d8217ae64d8aa90aec4fd81d680bd1acbfc2115f59c09acc61510b23b28fcef7083ecd51a5ce854f52d2ec8aab4b79b53599975c18b9d71f307d19f7a
6
+ metadata.gz: 9dbca39af63f07ddfe4d92618d0ff5e0813fa30561d42b629caa918f664f1149f8ad895e8555137b0f462eb4eac942adda07efed03859d17cb635a8d9bb25b57
7
+ data.tar.gz: 788d37c5d82e8892dfcfb6f4a8532f484f7cf17c5f937e8a64b09af902fe3a904ed034fc88d403852bbd8819a9d11ab61a672e2d6f3114420ed7777ea9db2961
@@ -1,5 +1,19 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
+ # Copyright 2020 Stanislav Senotrusov <stan@senotrusov.com>
4
+ #
5
+ # Licensed under the Apache License, Version 2.0 (the "License");
6
+ # you may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ # See the License for the specific language governing permissions and
15
+ # limitations under the License.
16
+
3
17
  require 'file-digests'
4
18
 
5
19
  FileDigests.run_cli_utility
@@ -1,6 +1,21 @@
1
+ # Copyright 2020 Stanislav Senotrusov <stan@senotrusov.com>
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
1
15
  require "date"
2
16
  require "digest"
3
17
  require "fileutils"
18
+ require "find"
4
19
  require "openssl"
5
20
  require "optparse"
6
21
  require "pathname"
@@ -8,7 +23,8 @@ require "set"
8
23
  require "sqlite3"
9
24
 
10
25
  class FileDigests
11
- DIGEST_ALGORITHMS=["BLAKE2b512", "SHA3-256", "SHA512-256"]
26
+ VERSION = Gem.loaded_specs["file-digests"]&.version&.to_s
27
+ DIGEST_ALGORITHMS = ["BLAKE2b512", "SHA3-256", "SHA512-256"]
12
28
  LEGACY_DIGEST_ALGORITHMS = ["SHA512", "SHA256"]
13
29
 
14
30
  def self.canonical_digest_algorithm_name(string)
@@ -75,7 +91,12 @@ class FileDigests
75
91
  options[:quiet] = true
76
92
  end
77
93
 
78
- opts.on("-t", "--test", "Perform only the test, do not modify the digest database.") do
94
+ opts.on(
95
+ "-t", "--test",
96
+ "Perform a test to verify directory contents.",
97
+ "Compare actual files with the stored digests, check if any files are missing.",
98
+ "Digest database will not be modified."
99
+ ) do
79
100
  options[:test_only] = true
80
101
  end
81
102
 
@@ -96,6 +117,7 @@ class FileDigests
96
117
 
97
118
  def initialize files_path, digest_database_path, options = {}
98
119
  @options = options
120
+ @user_input_wait_time = 0
99
121
 
100
122
  initialize_paths files_path, digest_database_path
101
123
  initialize_database
@@ -139,8 +161,6 @@ class FileDigests
139
161
  @db.results_as_hash = true
140
162
  @db.busy_timeout = 5000
141
163
 
142
- file_digests_gem_version = Gem.loaded_specs["file-digests"]&.version&.to_s
143
-
144
164
  execute "PRAGMA encoding = 'UTF-8'"
145
165
  execute "PRAGMA locking_mode = 'EXCLUSIVE'"
146
166
  execute "PRAGMA journal_mode = 'WAL'"
@@ -155,14 +175,13 @@ class FileDigests
155
175
  execute "CREATE TABLE metadata (
156
176
  key TEXT NOT NULL PRIMARY KEY,
157
177
  value TEXT)"
158
- execute "CREATE UNIQUE INDEX metadata_key ON metadata(key)"
159
178
  metadata_table_was_created = true
160
179
  end
161
180
 
162
181
  prepare_method :set_metadata_query, "INSERT INTO metadata (key, value) VALUES (?, ?) ON CONFLICT (key) DO UPDATE SET value=excluded.value"
163
182
  prepare_method :get_metadata_query, "SELECT value FROM metadata WHERE key = ?"
164
183
 
165
- set_metadata("metadata_table_created_by_gem_version", file_digests_gem_version) if file_digests_gem_version && metadata_table_was_created
184
+ set_metadata("metadata_table_created_by_gem_version", FileDigests::VERSION) if FileDigests::VERSION && metadata_table_was_created
166
185
 
167
186
  # Heuristic to detect database version 1 (metadata was not stored back then)
168
187
  unless get_metadata("database_version")
@@ -179,20 +198,19 @@ class FileDigests
179
198
  digest TEXT NOT NULL,
180
199
  digest_check_time TEXT NOT NULL)"
181
200
  execute "CREATE UNIQUE INDEX digests_filename ON digests(filename)"
182
- set_metadata("digests_table_created_by_gem_version", file_digests_gem_version) if file_digests_gem_version
201
+ execute "CREATE INDEX digests_digest ON digests(digest)"
202
+ set_metadata("digests_table_created_by_gem_version", FileDigests::VERSION) if FileDigests::VERSION
183
203
  end
184
204
 
185
- prepare_method :insert, "INSERT INTO digests (filename, mtime, digest, digest_check_time) VALUES (?, ?, ?, datetime('now'))"
186
- prepare_method :find_by_filename_query, "SELECT id, mtime, digest FROM digests WHERE filename = ?"
187
- prepare_method :touch_digest_check_time, "UPDATE digests SET digest_check_time = datetime('now') WHERE id = ?"
188
- prepare_method :update_mtime_and_digest, "UPDATE digests SET mtime = ?, digest = ?, digest_check_time = datetime('now') WHERE id = ?"
189
- prepare_method :update_mtime, "UPDATE digests SET mtime = ?, digest_check_time = datetime('now') WHERE id = ?"
190
- prepare_method :delete_by_filename, "DELETE FROM digests WHERE filename = ?"
191
- prepare_method :query_duplicates, "SELECT digest, filename FROM digests WHERE digest IN (SELECT digest FROM digests GROUP BY digest HAVING count(*) > 1) ORDER BY digest, filename;"
192
- prepare_method :update_digest_to_new_digest, "UPDATE digests SET digest = ? WHERE digest = ?"
205
+ prepare_method :digests_insert, "INSERT INTO digests (filename, mtime, digest, digest_check_time) VALUES (?, ?, ?, datetime('now'))"
206
+ prepare_method :digests_find_by_filename_query, "SELECT id, mtime, digest FROM digests WHERE filename = ?"
207
+ prepare_method :digests_touch_check_time, "UPDATE digests SET digest_check_time = datetime('now') WHERE id = ?"
208
+ prepare_method :digests_update_mtime_and_digest, "UPDATE digests SET mtime = ?, digest = ?, digest_check_time = datetime('now') WHERE id = ?"
209
+ prepare_method :digests_update_mtime, "UPDATE digests SET mtime = ?, digest_check_time = datetime('now') WHERE id = ?"
210
+ prepare_method :digests_select_duplicates, "SELECT digest, filename FROM digests WHERE digest IN (SELECT digest FROM digests GROUP BY digest HAVING count(*) > 1) ORDER BY digest, filename;"
193
211
 
194
212
  unless get_metadata("database_version")
195
- set_metadata "database_version", "2"
213
+ set_metadata "database_version", "3"
196
214
  end
197
215
 
198
216
  # Convert database from 1st to 2nd version
@@ -207,79 +225,110 @@ class FileDigests
207
225
  end
208
226
  end
209
227
 
210
- if get_metadata("database_version") != "2"
211
- STDERR.puts "This version of file-digests (#{file_digests_gem_version || "unknown"}) is only compartible with the database version 2. Current database version is #{get_metadata("database_version")}. To use this database, please install appropriate version if file-digest."
212
- raise "Incompatible database version"
228
+ if get_metadata("database_version") == "2"
229
+ execute "CREATE INDEX digests_digest ON digests(digest)"
230
+ set_metadata "database_version", "3"
213
231
  end
232
+
233
+ check_if_database_is_at_certain_version "3"
234
+
235
+ create_temporary_tables
214
236
  end
215
237
  end
216
238
 
217
- def perform_check
218
- perhaps_transaction(@new_digest_algorithm, :exclusive) do
219
- @counters = {good: 0, updated: 0, new: 0, renamed: 0, likely_damaged: 0, exceptions: 0}
220
- @new_files = {}
221
- @new_digests = {}
239
+ def create_temporary_tables
240
+ execute "CREATE TEMPORARY TABLE new_files (
241
+ filename TEXT NOT NULL PRIMARY KEY,
242
+ digest TEXT NOT NULL)"
243
+ execute "CREATE INDEX new_files_digest ON new_files(digest)"
244
+
245
+ prepare_method :new_files_insert, "INSERT INTO new_files (filename, digest) VALUES (?, ?)"
246
+ prepare_method :new_files_count_query, "SELECT count(*) FROM new_files"
247
+
248
+ execute "CREATE TEMPORARY TABLE missing_files (
249
+ filename TEXT NOT NULL PRIMARY KEY,
250
+ digest TEXT NOT NULL)"
251
+ execute "CREATE INDEX missing_files_digest ON missing_files(digest)"
252
+
253
+ execute "INSERT INTO missing_files (filename, digest) SELECT filename, digest FROM digests"
254
+
255
+ prepare_method :missing_files_delete, "DELETE FROM missing_files WHERE filename = ?"
256
+ prepare_method :missing_files_delete_renamed_files, "DELETE FROM missing_files WHERE digest IN (SELECT digest FROM new_files)"
257
+ prepare_method :missing_files_select_all_filenames, "SELECT filename FROM missing_files ORDER BY filename"
258
+ prepare_method :missing_files_delete_all, "DELETE FROM missing_files"
259
+ prepare_method :missing_files_count_query, "SELECT count(*) FROM missing_files"
260
+
261
+ prepare_method :digests_delete_renamed_files, "DELETE FROM digests WHERE filename IN (SELECT filename FROM missing_files WHERE digest IN (SELECT digest FROM new_files))"
262
+ prepare_method :digests_delete_all_missing_files, "DELETE FROM digests WHERE filename IN (SELECT filename FROM missing_files)"
263
+
264
+ execute "CREATE TEMPORARY TABLE new_digests (
265
+ filename TEXT NOT NULL PRIMARY KEY,
266
+ digest TEXT NOT NULL)"
267
+
268
+ prepare_method :new_digests_insert, "INSERT INTO new_digests (filename, digest) VALUES (?, ?)"
269
+ prepare_method :digests_update_digests_to_new_digests, "INSERT INTO digests (filename, digest, digest_check_time) SELECT filename, digest, false FROM new_digests WHERE true ON CONFLICT (filename) DO UPDATE SET digest=excluded.digest"
270
+ end
222
271
 
223
- @missing_files = Hash[@db.prepare("SELECT filename, digest FROM digests").execute!]
272
+ def perform_check
273
+ measure_time do
274
+ perhaps_transaction(@new_digest_algorithm, :exclusive) do
275
+ @counters = {good: 0, updated: 0, renamed: 0, likely_damaged: 0, exceptions: 0}
224
276
 
225
- measure_time do
226
277
  walk_files do |filename|
227
278
  process_file filename
228
279
  end
229
- end
230
280
 
231
- nested_transaction do
232
- puts "Tracking renames..." if @options[:verbose]
233
- track_renames
234
- end
281
+ nested_transaction do
282
+ puts "Tracking renames..." if @options[:verbose]
283
+ track_renames
284
+ end
235
285
 
236
- if any_missing_files?
237
- if any_exceptions?
238
- STDERR.puts "Due to previously occurred errors, database cleanup from missing files will be skipped this time."
239
- else
240
- print_missing_files
241
- if !@options[:test_only] && (@options[:auto] || confirm("Remove missing files from the database"))
242
- nested_transaction do
243
- puts "Removing missing files..." if @options[:verbose]
244
- remove_missing_files
286
+ if any_missing_files?
287
+ if any_exceptions?
288
+ STDERR.puts "Due to previously occurred errors, missing files will not removed from the database."
289
+ else
290
+ print_missing_files
291
+ if !@options[:test_only] && (@options[:auto] || confirm("Remove missing files from the database"))
292
+ nested_transaction do
293
+ puts "Removing missing files..." if @options[:verbose]
294
+ remove_missing_files
295
+ end
245
296
  end
246
297
  end
247
298
  end
248
- end
249
299
 
250
- if @new_digest_algorithm && !@options[:test_only]
251
- if any_missing_files? || any_likely_damaged? || any_exceptions?
252
- STDERR.puts "ERROR: New digest algorithm will not be in effect until there are files that are missing, likely damaged, or processed with an exception."
253
- else
254
- puts "Updating database to a new digest algorithm..." if @options[:verbose]
255
- @new_digests.each do |old_digest, new_digest|
256
- update_digest_to_new_digest new_digest, old_digest
300
+ if @new_digest_algorithm && !@options[:test_only]
301
+ if any_missing_files? || any_likely_damaged? || any_exceptions?
302
+ STDERR.puts "ERROR: New digest algorithm will not be in effect until there are files that are missing, likely damaged, or processed with an exception."
303
+ else
304
+ puts "Updating database to a new digest algorithm..." if @options[:verbose]
305
+ digests_update_digests_to_new_digests
306
+ set_metadata "digest_algorithm", @new_digest_algorithm
307
+ puts "Transition to a new digest algorithm complete: #{@new_digest_algorithm}"
257
308
  end
258
- set_metadata "digest_algorithm", @new_digest_algorithm
259
- puts "Transition to a new digest algorithm complete: #{@new_digest_algorithm}"
260
309
  end
261
- end
262
310
 
263
- if any_likely_damaged? || any_exceptions?
264
- STDERR.puts "PLEASE REVIEW ERRORS THAT WERE OCCURRED!"
265
- end
311
+ if any_likely_damaged? || any_exceptions?
312
+ STDERR.puts "PLEASE REVIEW ERRORS THAT WERE OCCURRED!"
313
+ end
266
314
 
267
- set_metadata(@options[:test_only] ? "latest_test_only_check_time" : "latest_complete_check_time", time_to_database(Time.now))
315
+ set_metadata(@options[:test_only] ? "latest_test_only_check_time" : "latest_complete_check_time", time_to_database(Time.now))
268
316
 
269
- print_counters
270
- end
271
-
272
- puts "Performing database maintenance..." if @options[:verbose]
273
- execute "PRAGMA optimize"
274
- execute "VACUUM"
275
- execute "PRAGMA wal_checkpoint(TRUNCATE)"
317
+ print_counters
318
+ end
319
+
320
+ puts "Performing database maintenance..." if @options[:verbose]
321
+ execute "PRAGMA optimize"
322
+ execute "VACUUM"
323
+ execute "PRAGMA wal_checkpoint(TRUNCATE)"
276
324
 
277
- hide_database_files
325
+ hide_database_files
326
+ end
278
327
  end
279
328
 
280
329
  def show_duplicates
281
330
  current_digest = nil
282
- query_duplicates.each do |found|
331
+ digests_select_duplicates.each do |found|
283
332
  if current_digest != found["digest"]
284
333
  puts "" if current_digest
285
334
  current_digest = found["digest"]
@@ -311,9 +360,10 @@ class FileDigests
311
360
 
312
361
  normalized_filename = filename.delete_prefix("#{@files_path.to_s}/").encode("utf-8", universal_newline: true).unicode_normalize(:nfkc)
313
362
  mtime_string = time_to_database stat.mtime
314
- digest = get_file_digest(filename)
363
+ digest, new_digest = get_file_digest(filename)
315
364
 
316
365
  nested_transaction do
366
+ new_digests_insert(normalized_filename, new_digest) if new_digest
317
367
  process_file_indeed normalized_filename, mtime_string, digest
318
368
  end
319
369
 
@@ -331,15 +381,15 @@ class FileDigests
331
381
  end
332
382
 
333
383
  def process_previously_seen_file found, filename, mtime, digest
334
- @missing_files.delete(filename)
384
+ missing_files_delete filename
335
385
  if found["digest"] == digest
336
386
  @counters[:good] += 1
337
387
  puts "GOOD: #{filename}" if @options[:verbose]
338
388
  unless @options[:test_only]
339
389
  if found["mtime"] == mtime
340
- touch_digest_check_time found["id"]
390
+ digests_touch_check_time found["id"]
341
391
  else
342
- update_mtime mtime, found["id"]
392
+ digests_update_mtime mtime, found["id"]
343
393
  end
344
394
  end
345
395
  else
@@ -350,18 +400,17 @@ class FileDigests
350
400
  @counters[:updated] += 1
351
401
  puts "UPDATED#{" (FATE ACCEPTED)" if found["mtime"] == mtime && @options[:accept_fate]}: #{filename}" unless @options[:quiet]
352
402
  unless @options[:test_only]
353
- update_mtime_and_digest mtime, digest, found["id"]
403
+ digests_update_mtime_and_digest mtime, digest, found["id"]
354
404
  end
355
405
  end
356
406
  end
357
407
  end
358
408
 
359
409
  def process_new_file filename, mtime, digest
360
- @counters[:new] += 1
361
410
  puts "NEW: #{filename}" unless @options[:quiet]
411
+ new_files_insert filename, digest
362
412
  unless @options[:test_only]
363
- @new_files[filename] = digest
364
- insert filename, mtime, digest
413
+ digests_insert filename, mtime, digest
365
414
  end
366
415
  end
367
416
 
@@ -369,29 +418,31 @@ class FileDigests
369
418
  # Renames and missing files
370
419
 
371
420
  def track_renames
372
- @missing_files.delete_if do |filename, digest|
373
- if @new_files.value?(digest)
374
- @counters[:renamed] += 1
375
- unless @options[:test_only]
376
- delete_by_filename filename
377
- end
378
- true
379
- end
421
+ unless @options[:test_only]
422
+ digests_delete_renamed_files
380
423
  end
424
+ missing_files_delete_renamed_files
425
+ @counters[:renamed] = @db.changes
381
426
  end
382
427
 
383
428
  def print_missing_files
384
429
  puts "\nMISSING FILES:"
385
- @missing_files.sort.to_h.each do |filename, digest|
386
- puts filename
430
+ missing_files_select_all_filenames.each do |record|
431
+ puts record["filename"]
387
432
  end
388
433
  end
389
434
 
390
435
  def remove_missing_files
391
- @missing_files.each do |filename, digest|
392
- delete_by_filename filename
393
- end
394
- @missing_files = {}
436
+ digests_delete_all_missing_files
437
+ missing_files_delete_all
438
+ end
439
+
440
+ def missing_files_count
441
+ missing_files_count_query!&.first&.first
442
+ end
443
+
444
+ def any_missing_files?
445
+ missing_files_count > 0
395
446
  end
396
447
 
397
448
 
@@ -402,6 +453,7 @@ class FileDigests
402
453
  end
403
454
 
404
455
  def integrity_check
456
+ puts "Checking database integrity..." if @options[:verbose]
405
457
  if execute("PRAGMA integrity_check")&.first&.fetch("integrity_check") != "ok"
406
458
  raise "Database integrity check failed"
407
459
  end
@@ -456,7 +508,7 @@ class FileDigests
456
508
  end
457
509
 
458
510
  def find_by_filename filename
459
- result = find_by_filename_query filename
511
+ result = digests_find_by_filename_query filename
460
512
  found = result.next
461
513
  raise "Multiple records found" if result.next
462
514
  found
@@ -476,6 +528,18 @@ class FileDigests
476
528
  end
477
529
  end
478
530
 
531
+ def check_if_database_is_at_certain_version target_version
532
+ current_version = get_metadata("database_version")
533
+ if current_version != target_version
534
+ STDERR.puts "This version of file-digests (#{FileDigests::VERSION || "unknown"}) is only compartible with the database version #{target_version}. Current database version is #{current_version}. To use this database, please install appropriate version if file-digest."
535
+ raise "Incompatible database version"
536
+ end
537
+ end
538
+
539
+ def new_files_count
540
+ new_files_count_query!&.first&.first
541
+ end
542
+
479
543
 
480
544
  # Filesystem-related helpers
481
545
 
@@ -498,8 +562,8 @@ class FileDigests
498
562
  end
499
563
 
500
564
  def walk_files
501
- Dir.glob(@files_path + "**" + "*", File::FNM_DOTMATCH) do |filename|
502
- yield filename
565
+ Find.find(@files_path) do |path|
566
+ yield path
503
567
  end
504
568
  end
505
569
 
@@ -513,18 +577,13 @@ class FileDigests
513
577
  digest.update(buffer)
514
578
  new_digest.update(buffer) if @new_digest_algorithm
515
579
  end
516
- @new_digests[digest.hexdigest] = new_digest.hexdigest if @new_digest_algorithm
517
- return digest.hexdigest
580
+ return [digest.hexdigest, (new_digest.hexdigest if @new_digest_algorithm)]
518
581
  end
519
582
  end
520
583
 
521
584
 
522
585
  # Runtime state helpers
523
586
 
524
- def any_missing_files?
525
- @missing_files.length > 0
526
- end
527
-
528
587
  def any_exceptions?
529
588
  @counters[:exceptions] > 0
530
589
  end
@@ -538,14 +597,17 @@ class FileDigests
538
597
  def confirm text
539
598
  if STDIN.tty? && STDOUT.tty?
540
599
  puts "#{text} (y/n)?"
541
- STDIN.gets.strip.downcase == "y"
600
+ start = Process.clock_gettime(Process::CLOCK_MONOTONIC)
601
+ result = (STDIN.gets.strip.downcase == "y")
602
+ @user_input_wait_time += (Process.clock_gettime(Process::CLOCK_MONOTONIC) - start)
603
+ result
542
604
  end
543
605
  end
544
606
 
545
607
  def measure_time
546
608
  start = Process.clock_gettime(Process::CLOCK_MONOTONIC)
547
609
  yield
548
- elapsed = (Process.clock_gettime(Process::CLOCK_MONOTONIC) - start)
610
+ elapsed = (Process.clock_gettime(Process::CLOCK_MONOTONIC) - start) - @user_input_wait_time
549
611
  puts "Elapsed time: #{elapsed.to_i / 3600}h #{(elapsed.to_i % 3600) / 60}m #{"%.3f" % (elapsed % 60)}s" unless @options[:quiet]
550
612
  end
551
613
 
@@ -563,11 +625,14 @@ class FileDigests
563
625
  end
564
626
 
565
627
  def print_counters
628
+ missing_files_count_result = missing_files_count
629
+ new_files_count_result = new_files_count - @counters[:renamed]
630
+
566
631
  puts "#{@counters[:good]} file(s) passes digest check" if @counters[:good] > 0
567
632
  puts "#{@counters[:updated]} file(s) are updated" if @counters[:updated] > 0
568
- puts "#{@counters[:new]} file(s) are new" if @counters[:new] > 0
633
+ puts "#{new_files_count_result} file(s) are new" if new_files_count_result > 0
569
634
  puts "#{@counters[:renamed]} file(s) are renamed" if @counters[:renamed] > 0
570
- puts "#{@missing_files.length} file(s) are missing" if @missing_files.length > 0
635
+ puts "#{missing_files_count_result} file(s) are missing" if missing_files_count_result > 0
571
636
  puts "#{@counters[:likely_damaged]} file(s) are likely damaged (!)" if @counters[:likely_damaged] > 0
572
637
  puts "#{@counters[:exceptions]} file(s) had exceptions occured during processing (!)" if @counters[:exceptions] > 0
573
638
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: file-digests
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.31
4
+ version: 0.0.36
5
5
  platform: ruby
6
6
  authors:
7
7
  - Stanislav Senotrusov
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-10-15 00:00:00.000000000 Z
11
+ date: 2020-10-17 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: openssl