Class: Xamidimura::SourceRevision

Inherits:
Object
  • Object
show all
Defined in:
lib/xamidimura/source_revision.rb,
sig/xamidimura.rbs

Defined Under Namespace

Classes: Snapshot

Class Method Summary collapse

Class Method Details

.digest(bytes) ⇒ String

Parameters:

  • bytes (String)

Returns:

  • (String)

Raises:

  • (TypeError)


9
10
11
12
13
# File 'lib/xamidimura/source_revision.rb', line 9

def self.digest(bytes)
  raise TypeError, "source bytes must be a String" unless bytes.is_a?(String)

  Digest::SHA256.hexdigest(bytes)
end

.file_digest(path) ⇒ String

Parameters:

  • path (String)

Returns:

  • (String)


15
16
17
18
19
20
21
# File 'lib/xamidimura/source_revision.rb', line 15

def self.file_digest(path)
  raise TypeError, "path must be a String" unless path.is_a?(String)

  Digest::SHA256.file(path).hexdigest
rescue SystemCallError => error
  raise Error, error.message
end

.read(path, attempts: 3, reject_symlink: false) ⇒ Snapshot

Parameters:

  • path (String)
  • attempts: (Integer) (defaults to: 3)
  • reject_symlink: (Boolean) (defaults to: false)

Returns:



38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
# File 'lib/xamidimura/source_revision.rb', line 38

def self.read(path, attempts: 3, reject_symlink: false)
  unless attempts.is_a?(Integer) && attempts.between?(1, 10)
    raise ArgumentError, "attempts must be an integer between 1 and 10"
  end

  attempts.times do
    before = signature(path, reject_symlink: reject_symlink)
    bytes = File.binread(path)
    after = signature(path, reject_symlink: reject_symlink)
    next unless before == after

    return Snapshot.new(bytes.freeze, after, digest(bytes).freeze)
  end
  raise Error, "source file changed while it was being read; retry"
rescue SystemCallError => error
  raise Error, error.message
end

.signature(path, reject_symlink: false) ⇒ [Integer, Integer, Integer, Integer, Integer, Integer, Integer]

Parameters:

  • path (String)
  • reject_symlink: (Boolean) (defaults to: false)

Returns:

  • ([Integer, Integer, Integer, Integer, Integer, Integer, Integer])


23
24
25
26
27
28
29
30
31
32
33
34
35
36
# File 'lib/xamidimura/source_revision.rb', line 23

def self.signature(path, reject_symlink: false)
  raise TypeError, "path must be a String" unless path.is_a?(String)
  unless reject_symlink == true || reject_symlink == false
    raise ArgumentError, "reject_symlink must be true or false"
  end

  stat = reject_symlink ? File.lstat(path) : File.stat(path)
  raise Error, "source path is not a regular file" unless stat.file? && !(reject_symlink && stat.symlink?)

  [stat.dev, stat.ino, stat.size, stat.mtime.to_i, stat.mtime.nsec,
   stat.ctime.to_i, stat.ctime.nsec].freeze
rescue SystemCallError => error
  raise Error, error.message
end