Class: FileDigests::DigestDatabase

Inherits:
Object
  • Object
show all
Defined in:
lib/file-digests.rb

Instance Method Summary collapse

Constructor Details

#initialize(path, options = {}) ⇒ DigestDatabase

Returns a new instance of DigestDatabase.



21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
# File 'lib/file-digests.rb', line 21

def initialize path, options = {}
  @options = options

  @db = SQLite3::Database.new path.to_s
  @db.results_as_hash = true

  execute 'PRAGMA journal_mode = "WAL"'
  execute 'PRAGMA synchronous = "NORMAL"'
  execute 'PRAGMA locking_mode = "EXCLUSIVE"'
  execute 'PRAGMA cache_size = "5000"'

  unless execute("SELECT name FROM sqlite_master WHERE type='table' AND name = 'digests'").length == 1
    execute 'PRAGMA encoding = "UTF-8"'
    execute "CREATE TABLE digests (
      id INTEGER PRIMARY KEY,
      filename TEXT,
      mtime TEXT,
      digest TEXT,
      digest_check_time TEXT)"
    execute "CREATE UNIQUE INDEX digests_filename ON digests(filename)"
  end

  @missing_files = Hash[@db.prepare("SELECT filename, digest FROM digests").execute!]
  @new_files = {}

  prepare_method :insert, "INSERT INTO digests (filename, mtime, digest, digest_check_time) VALUES (?, ?, ?, datetime('now'))"
  prepare_method :find_by_filename, "SELECT id, mtime, digest FROM digests WHERE filename = ?"
  prepare_method :touch_digest_check_time, "UPDATE digests SET digest_check_time = datetime('now') WHERE id = ?"
  prepare_method :update_mtime_and_digest, "UPDATE digests SET mtime = ?, digest = ?, digest_check_time = datetime('now') WHERE id = ?"
  prepare_method :update_mtime, "UPDATE digests SET mtime = ?, digest_check_time = datetime('now') WHERE id = ?"
  prepare_method :delete_by_filename, "DELETE FROM digests WHERE filename = ?"
end

Instance Method Details

#any_missing_files?Boolean

Returns:

  • (Boolean)


107
108
109
# File 'lib/file-digests.rb', line 107

def any_missing_files?
  @missing_files.length > 0
end

#insert_or_update(file_path, mtime, digest, counters) ⇒ Object



54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
# File 'lib/file-digests.rb', line 54

def insert_or_update file_path, mtime, digest, counters
  result = find_by_filename file_path

  if found = result.next_hash
    raise "Multiple records found" if result.next

    @missing_files.delete(file_path)

    if found['digest'] == digest
      counters[:good] += 1
      # puts "GOOD: #{file_path}" unless @options[:quiet]
      unless @options[:test_only]
        if found['mtime'] == mtime
          touch_digest_check_time found['id']
        else
          update_mtime mtime, found['id']
        end
      end
    else
      if found['mtime'] == mtime # Digest is different and mtime is the same
        counters[:likely_damaged] += 1
        STDERR.puts "LIKELY DAMAGED: #{file_path}"
      else
        counters[:updated] += 1
        puts "UPDATED: #{file_path}" unless @options[:quiet]
        unless @options[:test_only]
          update_mtime_and_digest mtime, digest, found['id']
        end
      end
    end
  else
    counters[:new] += 1
    puts "NEW: #{file_path}" unless @options[:quiet]
    unless @options[:test_only]
      @new_files[file_path] = digest
      insert file_path, mtime, digest
    end
  end
end


111
112
113
114
115
116
# File 'lib/file-digests.rb', line 111

def print_missing_files
  puts "\nMISSING FILES:"
  @missing_files.sort.to_h.each do |filename, digest|
    puts filename
  end
end

#remove_missing_filesObject



118
119
120
121
122
123
124
# File 'lib/file-digests.rb', line 118

def remove_missing_files
  @db.transaction do
    @missing_files.each do |filename, digest|
      delete_by_filename filename
    end
  end
end

#track_renames(counters) ⇒ Object



94
95
96
97
98
99
100
101
102
103
104
105
# File 'lib/file-digests.rb', line 94

def track_renames counters
  @missing_files.delete_if do |filename, digest|
    if @new_files.value?(digest)
      counters[:renamed] += 1
      unless @options[:test_only]
        delete_by_filename filename
      end
      true
    end
  end
  counters[:missing] = @missing_files.length
end