file-digests 0.0.31 → 0.0.36

Sign up to get free protection for your applications and to get access to all the features.
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