Class: DirectoryDigest::Digest

Inherits:
Object
  • Object
show all
Defined in:
lib/directory-digest/digest.rb

Overview

DirectoryDigest::Digest - Creates a SHA256 digest of a directory’s content.

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(directory, directory_digest, file_digests, files_excluded) ⇒ Digest

Returns a new instance of Digest.



13
14
15
16
17
18
# File 'lib/directory-digest/digest.rb', line 13

def initialize(directory, directory_digest, file_digests, files_excluded)
  @directory = directory.freeze
  @directory_digest = directory_digest.freeze
  @file_digests = file_digests.freeze
  @files_excluded = files_excluded.freeze
end

Instance Attribute Details

#directoryObject (readonly)

Returns the value of attribute directory.



8
9
10
# File 'lib/directory-digest/digest.rb', line 8

def directory
  @directory
end

#directory_digestObject (readonly)

Returns the value of attribute directory_digest.



9
10
11
# File 'lib/directory-digest/digest.rb', line 9

def directory_digest
  @directory_digest
end

#file_digestsObject (readonly)

Returns the value of attribute file_digests.



10
11
12
# File 'lib/directory-digest/digest.rb', line 10

def file_digests
  @file_digests
end

#files_excludedObject (readonly)

Returns the value of attribute files_excluded.



11
12
13
# File 'lib/directory-digest/digest.rb', line 11

def files_excluded
  @files_excluded
end

Class Method Details

.from_json(json) ⇒ Object



98
99
100
101
102
103
104
# File 'lib/directory-digest/digest.rb', line 98

def self.from_json(json)
  json = JSON.parse(json)
  Digest.new(json['directory'],
             json['directory_digest'],
             json['file_digests'],
             json['files_excluded'])
end

.sha256(directory, glob = '**/*', include = proc { true }) ⇒ Object



20
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
# File 'lib/directory-digest/digest.rb', line 20

def self.sha256(directory, glob = '**/*', include = proc { true })
  if include.is_a?(Array)
    regex_list = include
    include = lambda do |path|
      matches = regex_list.select { |regex| regex.size > 1 && path =~ /#{regex[1..-1]}/ }
      matches.count.zero? || matches.last[0] == '+'
    end
  end
  directory_digest = OpenSSL::Digest::SHA256.new
  file_digests = {}
  files_excluded = []
  Dir["#{directory}/#{glob}"].each do |filename|
    next unless File.file?(filename)
    path = filename[directory.size..-1]
    if include.call(path)
      file_digest = OpenSSL::Digest::SHA256.new
      File.open(filename, 'rb') do |file|
        until file.eof?
          chunk = file.read(4096)
          directory_digest << chunk
          file_digest << chunk
        end
      end
      file_digests[path] = file_digest.hexdigest
    else
      files_excluded << path
    end
  end
  Digest.new(directory, directory_digest.hexdigest, file_digests, files_excluded)
end

Instance Method Details

#!=(other) ⇒ Object



55
56
57
# File 'lib/directory-digest/digest.rb', line 55

def !=(other)
  directory_digest != other.directory_digest
end

#==(other) ⇒ Object



51
52
53
# File 'lib/directory-digest/digest.rb', line 51

def ==(other)
  directory_digest == other.directory_digest
end

#changes_relative_to(other) ⇒ Object



59
60
61
62
63
64
65
66
67
# File 'lib/directory-digest/digest.rb', line 59

def changes_relative_to(other)
  {
    added: file_digests.select { |path, _| !other.file_digests.key?(path) },
    removed: other.file_digests.select { |path, _| !file_digests.key?(path) },
    changed: other.file_digests.select { |path, digest| file_digests.key?(path) && digest != file_digests[path] },
    unchanged: other.file_digests.select { |path, digest| file_digests.key?(path) && digest == file_digests[path] },
    excluded: files_excluded | other.files_excluded
  }
end

#mirror_from(other, actions = MirrorActions.new) ⇒ Object



69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
# File 'lib/directory-digest/digest.rb', line 69

def mirror_from(other, actions = MirrorActions.new)
  changes = changes_relative_to(other)
  to_copy = changes[:removed].merge(changes[:changed])
  to_copy.keys.each do |path|
    source_path = "#{other.directory}#{path}"
    destination_path = "#{directory}#{path}"
    destination_directory = File.dirname(destination_path)
    actions.create_directory(destination_directory) unless Dir.exist?(destination_directory)
    actions.copy_file(source_path, destination_path)
  end
  to_delete = changes[:added]
  to_delete.keys.each do |path|
    actions.delete_file("#{directory}#{path}")
  end
  {
    copied: to_copy,
    deleted: to_delete,
    unchanged: changes[:unchanged],
    excluded: changes[:excluded]
  }
end

#to_jsonObject



91
92
93
94
95
96
# File 'lib/directory-digest/digest.rb', line 91

def to_json
  JSON.pretty_generate(directory: directory,
                       directory_digest: directory_digest,
                       file_digests: file_digests,
                       files_excluded: files_excluded)
end