file-digests 0.0.33 → 0.0.34
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/bin/file-digests +14 -0
- data/lib/file-digests.rb +154 -96
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: dd11bc930ad2146b6e9bbecd44479df1817c8262197a184f19d5db03296d16c1
|
|
4
|
+
data.tar.gz: 60a3741b3b6d7cfa714991bac995176398e4834a53106751b55d537a9e9ac901
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 2cfbe4ac1169e5b48c9bb0c1ee3200fa060e38bc770200d14a127f98ab3967f83476f35130f4bd9d8427bbe7cac07c33b43e14c086e5897921c7383f0748cbfe
|
|
7
|
+
data.tar.gz: 9a5830dc67eb127ff39a0fffda53193d5ad43cfe25405e56d7bd211475af69192f404433c02f2c83d0c3f79dd4a56e4a02f469dbaad52abf6ab2027d8f9894bf
|
data/bin/file-digests
CHANGED
|
@@ -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
|
data/lib/file-digests.rb
CHANGED
|
@@ -1,3 +1,17 @@
|
|
|
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"
|
|
@@ -8,7 +22,8 @@ require "set"
|
|
|
8
22
|
require "sqlite3"
|
|
9
23
|
|
|
10
24
|
class FileDigests
|
|
11
|
-
|
|
25
|
+
VERSION = Gem.loaded_specs["file-digests"]&.version&.to_s
|
|
26
|
+
DIGEST_ALGORITHMS = ["BLAKE2b512", "SHA3-256", "SHA512-256"]
|
|
12
27
|
LEGACY_DIGEST_ALGORITHMS = ["SHA512", "SHA256"]
|
|
13
28
|
|
|
14
29
|
def self.canonical_digest_algorithm_name(string)
|
|
@@ -101,6 +116,7 @@ class FileDigests
|
|
|
101
116
|
|
|
102
117
|
def initialize files_path, digest_database_path, options = {}
|
|
103
118
|
@options = options
|
|
119
|
+
@user_input_wait_time = 0
|
|
104
120
|
|
|
105
121
|
initialize_paths files_path, digest_database_path
|
|
106
122
|
initialize_database
|
|
@@ -144,8 +160,6 @@ class FileDigests
|
|
|
144
160
|
@db.results_as_hash = true
|
|
145
161
|
@db.busy_timeout = 5000
|
|
146
162
|
|
|
147
|
-
file_digests_gem_version = Gem.loaded_specs["file-digests"]&.version&.to_s
|
|
148
|
-
|
|
149
163
|
execute "PRAGMA encoding = 'UTF-8'"
|
|
150
164
|
execute "PRAGMA locking_mode = 'EXCLUSIVE'"
|
|
151
165
|
execute "PRAGMA journal_mode = 'WAL'"
|
|
@@ -160,14 +174,13 @@ class FileDigests
|
|
|
160
174
|
execute "CREATE TABLE metadata (
|
|
161
175
|
key TEXT NOT NULL PRIMARY KEY,
|
|
162
176
|
value TEXT)"
|
|
163
|
-
execute "CREATE UNIQUE INDEX metadata_key ON metadata(key)"
|
|
164
177
|
metadata_table_was_created = true
|
|
165
178
|
end
|
|
166
179
|
|
|
167
180
|
prepare_method :set_metadata_query, "INSERT INTO metadata (key, value) VALUES (?, ?) ON CONFLICT (key) DO UPDATE SET value=excluded.value"
|
|
168
181
|
prepare_method :get_metadata_query, "SELECT value FROM metadata WHERE key = ?"
|
|
169
182
|
|
|
170
|
-
set_metadata("metadata_table_created_by_gem_version",
|
|
183
|
+
set_metadata("metadata_table_created_by_gem_version", FileDigests::VERSION) if FileDigests::VERSION && metadata_table_was_created
|
|
171
184
|
|
|
172
185
|
# Heuristic to detect database version 1 (metadata was not stored back then)
|
|
173
186
|
unless get_metadata("database_version")
|
|
@@ -184,20 +197,19 @@ class FileDigests
|
|
|
184
197
|
digest TEXT NOT NULL,
|
|
185
198
|
digest_check_time TEXT NOT NULL)"
|
|
186
199
|
execute "CREATE UNIQUE INDEX digests_filename ON digests(filename)"
|
|
187
|
-
|
|
200
|
+
execute "CREATE INDEX digests_digest ON digests(digest)"
|
|
201
|
+
set_metadata("digests_table_created_by_gem_version", FileDigests::VERSION) if FileDigests::VERSION
|
|
188
202
|
end
|
|
189
203
|
|
|
190
|
-
prepare_method :
|
|
191
|
-
prepare_method :
|
|
192
|
-
prepare_method :
|
|
193
|
-
prepare_method :
|
|
194
|
-
prepare_method :
|
|
195
|
-
prepare_method :
|
|
196
|
-
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;"
|
|
197
|
-
prepare_method :update_digest_to_new_digest, "UPDATE digests SET digest = ? WHERE digest = ?"
|
|
204
|
+
prepare_method :digests_insert, "INSERT INTO digests (filename, mtime, digest, digest_check_time) VALUES (?, ?, ?, datetime('now'))"
|
|
205
|
+
prepare_method :digests_find_by_filename_query, "SELECT id, mtime, digest FROM digests WHERE filename = ?"
|
|
206
|
+
prepare_method :digests_touch_check_time, "UPDATE digests SET digest_check_time = datetime('now') WHERE id = ?"
|
|
207
|
+
prepare_method :digests_update_mtime_and_digest, "UPDATE digests SET mtime = ?, digest = ?, digest_check_time = datetime('now') WHERE id = ?"
|
|
208
|
+
prepare_method :digests_update_mtime, "UPDATE digests SET mtime = ?, digest_check_time = datetime('now') WHERE id = ?"
|
|
209
|
+
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;"
|
|
198
210
|
|
|
199
211
|
unless get_metadata("database_version")
|
|
200
|
-
set_metadata "database_version", "
|
|
212
|
+
set_metadata "database_version", "3"
|
|
201
213
|
end
|
|
202
214
|
|
|
203
215
|
# Convert database from 1st to 2nd version
|
|
@@ -212,79 +224,110 @@ class FileDigests
|
|
|
212
224
|
end
|
|
213
225
|
end
|
|
214
226
|
|
|
215
|
-
if get_metadata("database_version")
|
|
216
|
-
|
|
217
|
-
|
|
227
|
+
if get_metadata("database_version") == "2"
|
|
228
|
+
execute "CREATE INDEX digests_digest ON digests(digest)"
|
|
229
|
+
set_metadata "database_version", "3"
|
|
218
230
|
end
|
|
231
|
+
|
|
232
|
+
check_if_database_is_at_certain_version "3"
|
|
233
|
+
|
|
234
|
+
create_temporary_tables
|
|
219
235
|
end
|
|
220
236
|
end
|
|
221
237
|
|
|
222
|
-
def
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
238
|
+
def create_temporary_tables
|
|
239
|
+
execute "CREATE TEMPORARY TABLE new_files (
|
|
240
|
+
filename TEXT NOT NULL PRIMARY KEY,
|
|
241
|
+
digest TEXT NOT NULL)"
|
|
242
|
+
execute "CREATE INDEX new_files_digest ON new_files(digest)"
|
|
243
|
+
|
|
244
|
+
prepare_method :new_files_insert, "INSERT INTO new_files (filename, digest) VALUES (?, ?)"
|
|
245
|
+
prepare_method :new_files_count_query, "SELECT count(*) FROM new_files"
|
|
246
|
+
|
|
247
|
+
execute "CREATE TEMPORARY TABLE missing_files (
|
|
248
|
+
filename TEXT NOT NULL PRIMARY KEY,
|
|
249
|
+
digest TEXT NOT NULL)"
|
|
250
|
+
execute "CREATE INDEX missing_files_digest ON missing_files(digest)"
|
|
227
251
|
|
|
228
|
-
|
|
252
|
+
execute "INSERT INTO missing_files (filename, digest) SELECT filename, digest FROM digests"
|
|
253
|
+
|
|
254
|
+
prepare_method :missing_files_delete, "DELETE FROM missing_files WHERE filename = ?"
|
|
255
|
+
prepare_method :missing_files_delete_renamed_files, "DELETE FROM missing_files WHERE digest IN (SELECT digest FROM new_files)"
|
|
256
|
+
prepare_method :missing_files_select_all_filenames, "SELECT filename FROM missing_files ORDER BY filename"
|
|
257
|
+
prepare_method :missing_files_delete_all, "DELETE FROM missing_files"
|
|
258
|
+
prepare_method :missing_files_count_query, "SELECT count(*) FROM missing_files"
|
|
259
|
+
|
|
260
|
+
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))"
|
|
261
|
+
prepare_method :digests_delete_all_missing_files, "DELETE FROM digests WHERE filename IN (SELECT filename FROM missing_files)"
|
|
262
|
+
|
|
263
|
+
execute "CREATE TEMPORARY TABLE new_digests (
|
|
264
|
+
filename TEXT NOT NULL PRIMARY KEY,
|
|
265
|
+
digest TEXT NOT NULL)"
|
|
266
|
+
|
|
267
|
+
prepare_method :new_digests_insert, "INSERT INTO new_digests (filename, digest) VALUES (?, ?)"
|
|
268
|
+
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"
|
|
269
|
+
end
|
|
270
|
+
|
|
271
|
+
def perform_check
|
|
272
|
+
measure_time do
|
|
273
|
+
perhaps_transaction(@new_digest_algorithm, :exclusive) do
|
|
274
|
+
@counters = {good: 0, updated: 0, renamed: 0, likely_damaged: 0, exceptions: 0}
|
|
229
275
|
|
|
230
|
-
measure_time do
|
|
231
276
|
walk_files do |filename|
|
|
232
277
|
process_file filename
|
|
233
278
|
end
|
|
234
|
-
end
|
|
235
279
|
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
280
|
+
nested_transaction do
|
|
281
|
+
puts "Tracking renames..." if @options[:verbose]
|
|
282
|
+
track_renames
|
|
283
|
+
end
|
|
240
284
|
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
285
|
+
if any_missing_files?
|
|
286
|
+
if any_exceptions?
|
|
287
|
+
STDERR.puts "Due to previously occurred errors, missing files will not removed from the database."
|
|
288
|
+
else
|
|
289
|
+
print_missing_files
|
|
290
|
+
if !@options[:test_only] && (@options[:auto] || confirm("Remove missing files from the database"))
|
|
291
|
+
nested_transaction do
|
|
292
|
+
puts "Removing missing files..." if @options[:verbose]
|
|
293
|
+
remove_missing_files
|
|
294
|
+
end
|
|
250
295
|
end
|
|
251
296
|
end
|
|
252
297
|
end
|
|
253
|
-
end
|
|
254
298
|
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
299
|
+
if @new_digest_algorithm && !@options[:test_only]
|
|
300
|
+
if any_missing_files? || any_likely_damaged? || any_exceptions?
|
|
301
|
+
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."
|
|
302
|
+
else
|
|
303
|
+
puts "Updating database to a new digest algorithm..." if @options[:verbose]
|
|
304
|
+
digests_update_digests_to_new_digests
|
|
305
|
+
set_metadata "digest_algorithm", @new_digest_algorithm
|
|
306
|
+
puts "Transition to a new digest algorithm complete: #{@new_digest_algorithm}"
|
|
262
307
|
end
|
|
263
|
-
set_metadata "digest_algorithm", @new_digest_algorithm
|
|
264
|
-
puts "Transition to a new digest algorithm complete: #{@new_digest_algorithm}"
|
|
265
308
|
end
|
|
266
|
-
end
|
|
267
309
|
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
310
|
+
if any_likely_damaged? || any_exceptions?
|
|
311
|
+
STDERR.puts "PLEASE REVIEW ERRORS THAT WERE OCCURRED!"
|
|
312
|
+
end
|
|
271
313
|
|
|
272
|
-
|
|
314
|
+
set_metadata(@options[:test_only] ? "latest_test_only_check_time" : "latest_complete_check_time", time_to_database(Time.now))
|
|
273
315
|
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
316
|
+
print_counters
|
|
317
|
+
end
|
|
318
|
+
|
|
319
|
+
puts "Performing database maintenance..." if @options[:verbose]
|
|
320
|
+
execute "PRAGMA optimize"
|
|
321
|
+
execute "VACUUM"
|
|
322
|
+
execute "PRAGMA wal_checkpoint(TRUNCATE)"
|
|
281
323
|
|
|
282
|
-
|
|
324
|
+
hide_database_files
|
|
325
|
+
end
|
|
283
326
|
end
|
|
284
327
|
|
|
285
328
|
def show_duplicates
|
|
286
329
|
current_digest = nil
|
|
287
|
-
|
|
330
|
+
digests_select_duplicates.each do |found|
|
|
288
331
|
if current_digest != found["digest"]
|
|
289
332
|
puts "" if current_digest
|
|
290
333
|
current_digest = found["digest"]
|
|
@@ -316,9 +359,10 @@ class FileDigests
|
|
|
316
359
|
|
|
317
360
|
normalized_filename = filename.delete_prefix("#{@files_path.to_s}/").encode("utf-8", universal_newline: true).unicode_normalize(:nfkc)
|
|
318
361
|
mtime_string = time_to_database stat.mtime
|
|
319
|
-
digest = get_file_digest(filename)
|
|
362
|
+
digest, new_digest = get_file_digest(filename)
|
|
320
363
|
|
|
321
364
|
nested_transaction do
|
|
365
|
+
new_digests_insert(normalized_filename, new_digest) if new_digest
|
|
322
366
|
process_file_indeed normalized_filename, mtime_string, digest
|
|
323
367
|
end
|
|
324
368
|
|
|
@@ -336,15 +380,15 @@ class FileDigests
|
|
|
336
380
|
end
|
|
337
381
|
|
|
338
382
|
def process_previously_seen_file found, filename, mtime, digest
|
|
339
|
-
|
|
383
|
+
missing_files_delete filename
|
|
340
384
|
if found["digest"] == digest
|
|
341
385
|
@counters[:good] += 1
|
|
342
386
|
puts "GOOD: #{filename}" if @options[:verbose]
|
|
343
387
|
unless @options[:test_only]
|
|
344
388
|
if found["mtime"] == mtime
|
|
345
|
-
|
|
389
|
+
digests_touch_check_time found["id"]
|
|
346
390
|
else
|
|
347
|
-
|
|
391
|
+
digests_update_mtime mtime, found["id"]
|
|
348
392
|
end
|
|
349
393
|
end
|
|
350
394
|
else
|
|
@@ -355,18 +399,17 @@ class FileDigests
|
|
|
355
399
|
@counters[:updated] += 1
|
|
356
400
|
puts "UPDATED#{" (FATE ACCEPTED)" if found["mtime"] == mtime && @options[:accept_fate]}: #{filename}" unless @options[:quiet]
|
|
357
401
|
unless @options[:test_only]
|
|
358
|
-
|
|
402
|
+
digests_update_mtime_and_digest mtime, digest, found["id"]
|
|
359
403
|
end
|
|
360
404
|
end
|
|
361
405
|
end
|
|
362
406
|
end
|
|
363
407
|
|
|
364
408
|
def process_new_file filename, mtime, digest
|
|
365
|
-
@counters[:new] += 1
|
|
366
409
|
puts "NEW: #{filename}" unless @options[:quiet]
|
|
410
|
+
new_files_insert filename, digest
|
|
367
411
|
unless @options[:test_only]
|
|
368
|
-
|
|
369
|
-
insert filename, mtime, digest
|
|
412
|
+
digests_insert filename, mtime, digest
|
|
370
413
|
end
|
|
371
414
|
end
|
|
372
415
|
|
|
@@ -374,29 +417,31 @@ class FileDigests
|
|
|
374
417
|
# Renames and missing files
|
|
375
418
|
|
|
376
419
|
def track_renames
|
|
377
|
-
@
|
|
378
|
-
|
|
379
|
-
@counters[:renamed] += 1
|
|
380
|
-
unless @options[:test_only]
|
|
381
|
-
delete_by_filename filename
|
|
382
|
-
end
|
|
383
|
-
true
|
|
384
|
-
end
|
|
420
|
+
unless @options[:test_only]
|
|
421
|
+
digests_delete_renamed_files
|
|
385
422
|
end
|
|
423
|
+
missing_files_delete_renamed_files
|
|
424
|
+
@counters[:renamed] = @db.changes
|
|
386
425
|
end
|
|
387
426
|
|
|
388
427
|
def print_missing_files
|
|
389
428
|
puts "\nMISSING FILES:"
|
|
390
|
-
|
|
391
|
-
puts filename
|
|
429
|
+
missing_files_select_all_filenames.each do |record|
|
|
430
|
+
puts record["filename"]
|
|
392
431
|
end
|
|
393
432
|
end
|
|
394
433
|
|
|
395
434
|
def remove_missing_files
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
435
|
+
digests_delete_all_missing_files
|
|
436
|
+
missing_files_delete_all
|
|
437
|
+
end
|
|
438
|
+
|
|
439
|
+
def missing_files_count
|
|
440
|
+
missing_files_count_query!&.first&.first
|
|
441
|
+
end
|
|
442
|
+
|
|
443
|
+
def any_missing_files?
|
|
444
|
+
missing_files_count > 0
|
|
400
445
|
end
|
|
401
446
|
|
|
402
447
|
|
|
@@ -461,7 +506,7 @@ class FileDigests
|
|
|
461
506
|
end
|
|
462
507
|
|
|
463
508
|
def find_by_filename filename
|
|
464
|
-
result =
|
|
509
|
+
result = digests_find_by_filename_query filename
|
|
465
510
|
found = result.next
|
|
466
511
|
raise "Multiple records found" if result.next
|
|
467
512
|
found
|
|
@@ -481,6 +526,18 @@ class FileDigests
|
|
|
481
526
|
end
|
|
482
527
|
end
|
|
483
528
|
|
|
529
|
+
def check_if_database_is_at_certain_version target_version
|
|
530
|
+
current_version = get_metadata("database_version")
|
|
531
|
+
if current_version != target_version
|
|
532
|
+
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."
|
|
533
|
+
raise "Incompatible database version"
|
|
534
|
+
end
|
|
535
|
+
end
|
|
536
|
+
|
|
537
|
+
def new_files_count
|
|
538
|
+
new_files_count_query!&.first&.first
|
|
539
|
+
end
|
|
540
|
+
|
|
484
541
|
|
|
485
542
|
# Filesystem-related helpers
|
|
486
543
|
|
|
@@ -519,18 +576,13 @@ class FileDigests
|
|
|
519
576
|
digest.update(buffer)
|
|
520
577
|
new_digest.update(buffer) if @new_digest_algorithm
|
|
521
578
|
end
|
|
522
|
-
|
|
523
|
-
return digest.hexdigest
|
|
579
|
+
return [digest.hexdigest, (new_digest.hexdigest if @new_digest_algorithm)]
|
|
524
580
|
end
|
|
525
581
|
end
|
|
526
582
|
|
|
527
583
|
|
|
528
584
|
# Runtime state helpers
|
|
529
585
|
|
|
530
|
-
def any_missing_files?
|
|
531
|
-
@missing_files.length > 0
|
|
532
|
-
end
|
|
533
|
-
|
|
534
586
|
def any_exceptions?
|
|
535
587
|
@counters[:exceptions] > 0
|
|
536
588
|
end
|
|
@@ -544,14 +596,17 @@ class FileDigests
|
|
|
544
596
|
def confirm text
|
|
545
597
|
if STDIN.tty? && STDOUT.tty?
|
|
546
598
|
puts "#{text} (y/n)?"
|
|
547
|
-
|
|
599
|
+
start = Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
|
600
|
+
result = (STDIN.gets.strip.downcase == "y")
|
|
601
|
+
@user_input_wait_time += (Process.clock_gettime(Process::CLOCK_MONOTONIC) - start)
|
|
602
|
+
result
|
|
548
603
|
end
|
|
549
604
|
end
|
|
550
605
|
|
|
551
606
|
def measure_time
|
|
552
607
|
start = Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
|
553
608
|
yield
|
|
554
|
-
elapsed = (Process.clock_gettime(Process::CLOCK_MONOTONIC) - start)
|
|
609
|
+
elapsed = (Process.clock_gettime(Process::CLOCK_MONOTONIC) - start) - @user_input_wait_time
|
|
555
610
|
puts "Elapsed time: #{elapsed.to_i / 3600}h #{(elapsed.to_i % 3600) / 60}m #{"%.3f" % (elapsed % 60)}s" unless @options[:quiet]
|
|
556
611
|
end
|
|
557
612
|
|
|
@@ -569,11 +624,14 @@ class FileDigests
|
|
|
569
624
|
end
|
|
570
625
|
|
|
571
626
|
def print_counters
|
|
627
|
+
missing_files_count_result = missing_files_count
|
|
628
|
+
new_files_count_result = new_files_count - @counters[:renamed]
|
|
629
|
+
|
|
572
630
|
puts "#{@counters[:good]} file(s) passes digest check" if @counters[:good] > 0
|
|
573
631
|
puts "#{@counters[:updated]} file(s) are updated" if @counters[:updated] > 0
|
|
574
|
-
puts "#{
|
|
632
|
+
puts "#{new_files_count_result} file(s) are new" if new_files_count_result > 0
|
|
575
633
|
puts "#{@counters[:renamed]} file(s) are renamed" if @counters[:renamed] > 0
|
|
576
|
-
puts "#{
|
|
634
|
+
puts "#{missing_files_count_result} file(s) are missing" if missing_files_count_result > 0
|
|
577
635
|
puts "#{@counters[:likely_damaged]} file(s) are likely damaged (!)" if @counters[:likely_damaged] > 0
|
|
578
636
|
puts "#{@counters[:exceptions]} file(s) had exceptions occured during processing (!)" if @counters[:exceptions] > 0
|
|
579
637
|
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.
|
|
4
|
+
version: 0.0.34
|
|
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-
|
|
11
|
+
date: 2020-10-17 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: openssl
|