file-digests 0.0.35 → 0.0.40

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 (3) hide show
  1. checksums.yaml +4 -4
  2. data/lib/file-digests.rb +103 -30
  3. metadata +2 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 42e870b2a0e4e711e84a2748d09d8a378fc6964d78706d573ab22737d0f2519e
4
- data.tar.gz: e14bef4ccd63fdc07950a257654c6594b793eabf44bbdf26cae59e621838e5c3
3
+ metadata.gz: a9d040599aee9aeb62234557b2a92edec36265e4439965e4c9d00a2c9afa117a
4
+ data.tar.gz: 992fe8a843afe761537a3c48b1ecde27ccdf8101be58dd4b456572c59232141b
5
5
  SHA512:
6
- metadata.gz: b6b9eb636258ba06b29bd21736b477c0d225ba119ad3b3ccb82612c941bf892109876aa4e8da7402f580f4167f84000a1b2b4ae91e568ac50f223325fab856ef
7
- data.tar.gz: afcdffefe0dcb346afcdf37ce6f3f523d4862a45a455838d8b7cbf603cead2c8fadbac185640088c79bd7e8c412b5da932bf301d90dd4337171b675a65f34388
6
+ metadata.gz: 1e15aa584690f8062a51cbb4785c9716e610258fba77859cb2b50642154701ffa1651312be1f6455921ee435ed7df5ed00bcc36f12def4009ac7edcc4aebb93e
7
+ data.tar.gz: 5c94ae4165677af0be7b790a7a92ffc9af7751f0dd2661bf238d06b02569ef4ec746908721c7d16781d11a431048759e1490f9e180ea9c2e647f5e585a3ebbe0
@@ -139,15 +139,29 @@ class FileDigests
139
139
  end
140
140
 
141
141
  def initialize_paths files_path, digest_database_path
142
+ @start_time_filename_string = Time.now.strftime("%Y-%m-%d %H-%M-%S")
142
143
  @files_path = cleanup_path(files_path || ".")
144
+ raise "ERROR: Files path must be a readable directory" unless (File.directory?(@files_path) && File.readable?(@files_path))
145
+ @files_path = realpath_with_disk @files_path
143
146
 
144
- raise "Files path must be a readable directory" unless (File.directory?(@files_path) && File.readable?(@files_path))
147
+ @error_log_path = @files_path + "file-digests errors #{@start_time_filename_string}.txt"
148
+ @missing_files_path = @files_path + "file-digests missing files #{@start_time_filename_string}.txt"
145
149
 
146
150
  @digest_database_path = digest_database_path ? cleanup_path(digest_database_path) : @files_path
147
151
  @digest_database_path += ".file-digests.sqlite" if File.directory?(@digest_database_path)
148
152
  ensure_dir_exist @digest_database_path.dirname
149
-
150
- @digest_database_files = ["#{@digest_database_path}", "#{@digest_database_path}-wal", "#{@digest_database_path}-shm"]
153
+ @digest_database_path = realdirpath_with_disk @digest_database_path
154
+
155
+ @digest_database_files = [
156
+ "#{@digest_database_path}",
157
+ "#{@digest_database_path}-wal",
158
+ "#{@digest_database_path}-shm"
159
+ ]
160
+
161
+ @skip_files = @digest_database_files + [
162
+ @error_log_path.to_s,
163
+ @missing_files_path.to_s
164
+ ]
151
165
 
152
166
  if @options[:verbose]
153
167
  puts "Target directory: #{@files_path}"
@@ -273,7 +287,7 @@ class FileDigests
273
287
  perhaps_transaction(@new_digest_algorithm, :exclusive) do
274
288
  @counters = {good: 0, updated: 0, renamed: 0, likely_damaged: 0, exceptions: 0}
275
289
 
276
- walk_files do |filename|
290
+ walk_files(@files_path.to_s) do |filename|
277
291
  process_file filename
278
292
  end
279
293
 
@@ -286,7 +300,7 @@ class FileDigests
286
300
  if any_exceptions?
287
301
  STDERR.puts "Due to previously occurred errors, missing files will not removed from the database."
288
302
  else
289
- print_missing_files
303
+ report_missing_files
290
304
  if !@options[:test_only] && (@options[:auto] || confirm("Remove missing files from the database"))
291
305
  nested_transaction do
292
306
  puts "Removing missing files..." if @options[:verbose]
@@ -340,9 +354,11 @@ class FileDigests
340
354
  private
341
355
 
342
356
  def process_file filename
343
- return if File.symlink? filename
357
+ perhaps_nt_filename = perhaps_nt_path filename
358
+
359
+ return if File.symlink? perhaps_nt_filename
344
360
 
345
- stat = File.stat filename
361
+ stat = File.stat perhaps_nt_filename
346
362
 
347
363
  return if stat.blockdev?
348
364
  return if stat.chardev?
@@ -352,23 +368,19 @@ class FileDigests
352
368
 
353
369
  raise "File is not readable" unless stat.readable?
354
370
 
355
- if @digest_database_files.include?(filename)
356
- puts "SKIPPING DATABASE FILE: #{filename}" if @options[:verbose]
371
+ if @skip_files.include?(filename)
372
+ puts "SKIPPING FILE: #{filename}" if @options[:verbose]
357
373
  return
358
374
  end
359
375
 
360
376
  normalized_filename = filename.delete_prefix("#{@files_path.to_s}/").encode("utf-8", universal_newline: true).unicode_normalize(:nfkc)
361
377
  mtime_string = time_to_database stat.mtime
362
- digest, new_digest = get_file_digest(filename)
378
+ digest, new_digest = get_file_digest(perhaps_nt_filename)
363
379
 
364
380
  nested_transaction do
365
381
  new_digests_insert(normalized_filename, new_digest) if new_digest
366
382
  process_file_indeed normalized_filename, mtime_string, digest
367
383
  end
368
-
369
- rescue => exception
370
- @counters[:exceptions] += 1
371
- print_file_exception exception, filename
372
384
  end
373
385
 
374
386
  def process_file_indeed filename, mtime, digest
@@ -394,7 +406,7 @@ class FileDigests
394
406
  else
395
407
  if found["mtime"] == mtime && !@options[:accept_fate] # Digest is different and mtime is the same
396
408
  @counters[:likely_damaged] += 1
397
- STDERR.puts "LIKELY DAMAGED: #{filename}"
409
+ error_text "LIKELY DAMAGED: #{filename}"
398
410
  else
399
411
  @counters[:updated] += 1
400
412
  puts "UPDATED#{" (FATE ACCEPTED)" if found["mtime"] == mtime && @options[:accept_fate]}: #{filename}" unless @options[:quiet]
@@ -424,10 +436,19 @@ class FileDigests
424
436
  @counters[:renamed] = @db.changes
425
437
  end
426
438
 
427
- def print_missing_files
439
+ def report_missing_files
428
440
  puts "\nMISSING FILES:"
441
+ write_missing_files STDOUT
442
+ if missing_files_count > 256
443
+ File.open(@missing_files_path, "a") do |f|
444
+ write_missing_files f
445
+ end
446
+ end
447
+ end
448
+
449
+ def write_missing_files dest
429
450
  missing_files_select_all_filenames.each do |record|
430
- puts record["filename"]
451
+ dest.puts record["filename"]
431
452
  end
432
453
  end
433
454
 
@@ -530,7 +551,7 @@ class FileDigests
530
551
  def check_if_database_is_at_certain_version target_version
531
552
  current_version = get_metadata("database_version")
532
553
  if current_version != target_version
533
- 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."
554
+ STDERR.puts "ERROR: 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."
534
555
  raise "Incompatible database version"
535
556
  end
536
557
  end
@@ -542,6 +563,22 @@ class FileDigests
542
563
 
543
564
  # Filesystem-related helpers
544
565
 
566
+ def realpath_with_disk path
567
+ path = path.realpath
568
+ if Gem.win_platform? && path.to_s[0] == "/"
569
+ return Pathname(Dir.pwd[0, 2] + path.to_s)
570
+ end
571
+ path
572
+ end
573
+
574
+ def realdirpath_with_disk path
575
+ path = path.realdirpath
576
+ if Gem.win_platform? && path.to_s[0] == "/"
577
+ return Pathname(Dir.pwd[0, 2] + path.to_s)
578
+ end
579
+ path
580
+ end
581
+
545
582
  def patch_path_string path
546
583
  Gem.win_platform? ? path.gsub(/\\/, "/") : path
547
584
  end
@@ -560,10 +597,32 @@ class FileDigests
560
597
  end
561
598
  end
562
599
 
563
- def walk_files
564
- puts "Gathering the list of files..." if @options[:verbose]
565
- Dir.glob(@files_path + "**" + "*", File::FNM_DOTMATCH) do |filename|
566
- yield filename
600
+ def walk_files(path, &block)
601
+ Dir.each_child(path, encoding: "UTF-8") do |item|
602
+ item = "#{path}#{File::SEPARATOR}#{item}"
603
+ begin
604
+ item_perhaps_nt_path = perhaps_nt_path item
605
+
606
+ unless File.symlink? item_perhaps_nt_path
607
+ if File.directory?(item_perhaps_nt_path)
608
+ raise "Directory is not readable" unless File.readable?(item_perhaps_nt_path)
609
+ walk_files(item, &block)
610
+ else
611
+ yield item
612
+ end
613
+ end
614
+ rescue => exception
615
+ @counters[:exceptions] += 1
616
+ report_file_exception exception, item
617
+ end
618
+ end
619
+ end
620
+
621
+ def perhaps_nt_path path
622
+ if Gem.win_platform?
623
+ "\\??\\#{path.gsub(/\//,"\\")}"
624
+ else
625
+ path
567
626
  end
568
627
  end
569
628
 
@@ -611,17 +670,31 @@ class FileDigests
611
670
  puts "Elapsed time: #{elapsed.to_i / 3600}h #{(elapsed.to_i % 3600) / 60}m #{"%.3f" % (elapsed % 60)}s" unless @options[:quiet]
612
671
  end
613
672
 
614
- def print_file_exception exception, filename
615
- STDERR.print "EXCEPTION: #{exception.message}, processing file: "
673
+ def report_file_exception exception, filename
674
+ write_file_exception STDERR, exception, filename
675
+ File.open(@error_log_path, "a") do |f|
676
+ write_file_exception f, exception, filename
677
+ end
678
+ end
679
+
680
+ def write_file_exception dest, exception, filename
681
+ dest.print "ERROR: #{exception.message}, processing file: "
616
682
  begin
617
- STDERR.print filename.encode("utf-8", universal_newline: true)
683
+ dest.print filename.encode("utf-8", universal_newline: true)
618
684
  rescue
619
- STDERR.print "(Unable to encode file name to utf-8) "
620
- STDERR.print filename
685
+ dest.print "(Unable to encode file name to utf-8) "
686
+ dest.print filename
687
+ end
688
+ dest.print "\n"
689
+ dest.flush
690
+ exception.backtrace.each { |line| dest.puts " " + line }
691
+ end
692
+
693
+ def error_text text
694
+ STDERR.puts text
695
+ File.open(@error_log_path, "a") do |f|
696
+ f.puts text
621
697
  end
622
- STDERR.print "\n"
623
- STDERR.flush
624
- exception.backtrace.each { |line| STDERR.puts " " + line }
625
698
  end
626
699
 
627
700
  def print_counters
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.35
4
+ version: 0.0.40
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-17 00:00:00.000000000 Z
11
+ date: 2020-10-20 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: openssl