Module: SugarUtils::File

Defined in:
lib/sugar_utils/file.rb

Defined Under Namespace

Classes: Error

Class Method Summary collapse

Class Method Details

.flock_exclusive(file, options = {}) ⇒ void

This method returns an undefined value.

Options Hash (options):

  • :timeout (Integer) — default: 10

Raises:

  • (Timeout::Error)


31
32
33
34
# File 'lib/sugar_utils/file.rb', line 31

def self.flock_exclusive(file, options = {})
  timeout = options[:timeout] || 10
  Timeout.timeout(timeout) { file.flock(::File::LOCK_EX) }
end

.flock_shared(file, options = {}) ⇒ void

This method returns an undefined value.

Options Hash (options):

  • :timeout (Integer) — default: 10

Raises:

  • (Timeout::Error)


19
20
21
22
# File 'lib/sugar_utils/file.rb', line 19

def self.flock_shared(file, options = {})
  timeout = options[:timeout] || 10
  Timeout.timeout(timeout) { file.flock(::File::LOCK_SH) }
end

.read(filename, options = {}) ⇒ String

Options Hash (options):

  • :timeout (Integer) — default: 10
  • :raise_on_missing (Boolean) — default: true
  • :value_on_missing (String) — default: ''

    which specifies the value to return if the file is missing and raise_on_missing is false

Raises:



46
47
48
49
50
51
52
53
54
55
56
57
58
59
# File 'lib/sugar_utils/file.rb', line 46

def self.read(filename, options = {})
  options[:value_on_missing] ||= ''
  options[:raise_on_missing] = true if options[:raise_on_missing].nil?

  ::File.open(filename, ::File::RDONLY) do |file|
    flock_shared(file, options)
    file.read
  end
rescue SystemCallError, IOError
  raise(Error, "Cannot read #{filename}") if options[:raise_on_missing]
  options[:value_on_missing]
rescue Timeout::Error
  raise(Error, "Cannot read #{filename} because it is locked")
end

.read_json(filename, options = {}) ⇒ Object

Options Hash (options):

  • :timeout (Integer) — default: 10
  • :raise_on_missing (Boolean) — default: true

Raises:



69
70
71
72
73
74
# File 'lib/sugar_utils/file.rb', line 69

def self.read_json(filename, options = {})
  options[:value_on_missing] = {}
  MultiJson.load(read(filename, options))
rescue MultiJson::ParseError
  raise(Error, "Cannot parse #{filename}")
end

.touch(filename, options = {}) ⇒ void

This method returns an undefined value.

Options Hash (options):

  • :owner (String, Integer)
  • :group (String, Integer)
  • :mode (Integer)
  • :perm (Integer)

    @deprecated



84
85
86
87
88
89
90
91
92
93
94
95
# File 'lib/sugar_utils/file.rb', line 84

def self.touch(filename, options = {})
  owner = options[:owner]
  group = options[:group]
  mode  = options[:mode] || options[:perm]

  deprecate_option(:touch, :perm, :mode, 2017, 8) if options.has_key?(:perm)

  FileUtils.mkdir_p(::File.dirname(filename))
  FileUtils.touch(filename)
  FileUtils.chown(owner, group, filename)
  FileUtils.chmod(mode, filename) if mode
end

.write(filename, data, options = {}) ⇒ void

This method returns an undefined value.

Options Hash (options):

  • :timeout (Integer) — default: 10
  • :flush (Boolean) — default: false
  • :owner (String, Integer)
  • :group (String, Integer)
  • :mode (Integer) — default: 0o644
  • :perm (Integer) — default: 0o644

    @deprecated

Raises:



110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
# File 'lib/sugar_utils/file.rb', line 110

def self.write(filename, data, options = {})
  flush = options[:flush] || false
  owner = options[:owner]
  group = options[:group]
  mode  = options[:mode] || options[:perm] || 0o644

  deprecate_option(:touch, :perm, :mode, 2017, 8) if options.has_key?(:perm)

  FileUtils.mkdir_p(::File.dirname(filename))
  ::File.open(filename, ::File::RDWR | ::File::CREAT, mode) do |file|
    flock_exclusive(file, options)

    file.truncate(0) # Ensure file is empty before proceeding.
    file.puts(data.to_s)

    # Flush and fsync to be 100% sure we write this data out now because we
    # are often reading it immediately and if the OS is buffering, it is
    # possible we might read it before it is been physically written to
    # disk. We are not worried about speed here, so this should be OKAY.
    if flush
      file.flush
      file.fsync
    end

    # Ensure that the permissions are correct if the file already existed.
    file.chmod(mode)
  end
  FileUtils.chown(owner, group, filename)
rescue Timeout::Error
  raise(Error, "Unable to write #{filename} because it is locked")
rescue SystemCallError, IOError => boom
  raise(Error, "Unable to write #{filename} with #{boom}")
end

.write_json(filename, data, options = {}) ⇒ void

This method returns an undefined value.

Options Hash (options):

  • :timeout (Integer) — default: 10
  • :flush (Boolean) — default: false
  • :perm (Integer) — default: 0644

Raises:



154
155
156
# File 'lib/sugar_utils/file.rb', line 154

def self.write_json(filename, data, options = {})
  write(filename, MultiJson.dump(data, pretty: true), options)
end