Class: RunLoop::Directory

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

Overview

Class for performing operations on directories.

Class Method Summary collapse

Class Method Details

.directory_digest(path, options = {}) ⇒ Object

Computes the digest of directory.

Parameters:

  • path

    A path to a directory.

  • options (defaults to: {})

    Control the behavior of the method.

Options Hash (options):

  • :handle_errors_by (Object) — default: :raising

    Controls what to do when File.read causes an error. The default behavior is to raise. Other options are: :logging and :ignoring. Logging will only happen if running in debug mode.

Raises:

  • ArgumentError When ‘path` is not a directory or path does not exist.

  • ArgumentError When options has n unsupported value.



33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
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
93
94
# File 'lib/run_loop/directory.rb', line 33

def self.directory_digest(path, options={})
  default_options = {
    :handle_errors_by => :raising
  }

  merged_options = default_options.merge(options)
  handle_errors_by = merged_options[:handle_errors_by]
  unless [:raising, :logging, :ignoring].include?(handle_errors_by)
    raise ArgumentError,
%Q{Expected :handle_errors_by to be :raising, :logging, or :ignoring;
found '#{handle_errors_by}'
}
  end

  unless File.exist?(path)
    raise ArgumentError, "Expected '#{path}' to exist"
  end

  unless File.directory?(path)
    raise ArgumentError, "Expected '#{path}' to be a directory"
  end

  entries = self.recursive_glob_for_entries(path)

  if entries.empty?
    raise ArgumentError, "Expected a non-empty dir at '#{path}' found '#{entries}'"
  end

  debug = RunLoop::Environment.debug?

  sha = OpenSSL::Digest::SHA256.new
  entries.each do |file|
    unless self.skip_file?(file, 'SHA1', debug)
      begin
        sha << File.read(file)
      rescue => e
        case handle_errors_by
        when :logging
          message =
%Q{RunLoop::Directory.directory_digest raised an error:

     #{e}

   while trying to find the SHA of this file:

     #{file}

   This is not a fatal error; it can be ignored.
}
          RunLoop.log_debug(message)
        when :raising
          raise e.class, e.message
        when :ignoring
           # nop
        else
           # nop
        end
      end
    end
  end
  sha.hexdigest
end

.recursive_glob_for_entries(base_dir) ⇒ Object

Dir.glob ignores files that start with ‘.’, but we often need to find dotted files and directories.

Ruby 2.* does the right thing by ignoring ‘..’ and ‘.’.

Ruby < 2.0 includes ‘..’ and ‘.’ in results which causes problems for some of run-loop’s internal methods. In particular ‘reset_app_sandbox`.



16
17
18
19
20
# File 'lib/run_loop/directory.rb', line 16

def self.recursive_glob_for_entries(base_dir)
  Dir.glob("#{base_dir}/{**/.*,**/*}").select do |entry|
    !(entry.end_with?('..') || entry.end_with?('.'))
  end
end

.size(path, format) ⇒ Object



96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
# File 'lib/run_loop/directory.rb', line 96

def self.size(path, format)

  allowed_formats = [:bytes, :kb, :mb, :gb]
  unless allowed_formats.include?(format)
    raise ArgumentError, "Expected '#{format}' to be one of #{allowed_formats.join(', ')}"
  end

  unless File.exist?(path)
    raise ArgumentError, "Expected '#{path}' to exist"
  end

  unless File.directory?(path)
    raise ArgumentError, "Expected '#{path}' to be a directory"
  end

  entries = self.recursive_glob_for_entries(path)

  if entries.empty?
    raise ArgumentError, "Expected a non-empty dir at '#{path}' found '#{entries}'"
  end

  size = self.iterate_for_size(entries)

  case format
    when :bytes
      size
    when :kb
      size/1000.0
    when :mb
      size/1000.0/1000.0
    when :gb
      size/1000.0/1000.0/1000.0
    else
      # Not expected to reach this.
      size
  end
end