hoodie 0.5.5 → 1.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (41) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/Gemfile +19 -0
  4. data/Rakefile +8 -23
  5. data/hoodie.gemspec +0 -23
  6. data/lib/hoodie.rb +40 -48
  7. data/lib/hoodie/configuration.rb +39 -2
  8. data/lib/hoodie/core_ext/blank.rb +6 -6
  9. data/lib/hoodie/core_ext/hash.rb +108 -13
  10. data/lib/hoodie/core_ext/string.rb +5 -3
  11. data/lib/hoodie/core_ext/try.rb +4 -3
  12. data/lib/hoodie/inflections.rb +18 -0
  13. data/lib/hoodie/inflections/defaults.rb +17 -0
  14. data/lib/hoodie/inflections/inflections.rb +17 -0
  15. data/lib/hoodie/inflections/rules_collection.rb +17 -0
  16. data/lib/hoodie/logging.rb +22 -4
  17. data/lib/hoodie/stash.rb +83 -80
  18. data/lib/hoodie/stash/disk_store.rb +142 -118
  19. data/lib/hoodie/stash/mem_store.rb +10 -9
  20. data/lib/hoodie/stash/memoizable.rb +46 -0
  21. data/lib/hoodie/utils.rb +13 -183
  22. data/lib/hoodie/utils/ansi.rb +199 -0
  23. data/lib/hoodie/utils/crypto.rb +288 -0
  24. data/lib/hoodie/utils/equalizer.rb +146 -0
  25. data/lib/hoodie/utils/file_helper.rb +225 -0
  26. data/lib/hoodie/utils/konstruktor.rb +77 -0
  27. data/lib/hoodie/utils/machine.rb +83 -0
  28. data/lib/hoodie/utils/os.rb +56 -0
  29. data/lib/hoodie/utils/retry.rb +235 -0
  30. data/lib/hoodie/utils/timeout.rb +54 -0
  31. data/lib/hoodie/utils/url_helper.rb +104 -0
  32. data/lib/hoodie/version.rb +4 -4
  33. metadata +13 -234
  34. data/lib/hoodie/identity_map.rb +0 -96
  35. data/lib/hoodie/memoizable.rb +0 -43
  36. data/lib/hoodie/obfuscate.rb +0 -121
  37. data/lib/hoodie/observable.rb +0 -309
  38. data/lib/hoodie/os.rb +0 -43
  39. data/lib/hoodie/proxy.rb +0 -68
  40. data/lib/hoodie/rash.rb +0 -125
  41. data/lib/hoodie/timers.rb +0 -355
@@ -1,8 +1,8 @@
1
1
  # encoding: UTF-8
2
2
  #
3
- # Author: Stefano Harding <riddopic@gmail.com>
4
- #
5
- # Copyright (C) 2014-2015 Stefano Harding
3
+ # Author: Stefano Harding <riddopic@gmail.com>
4
+ # License: Apache License, Version 2.0
5
+ # Copyright: (C) 2014-2015 Stefano Harding
6
6
  #
7
7
  # Licensed under the Apache License, Version 2.0 (the "License");
8
8
  # you may not use this file except in compliance with the License.
@@ -41,6 +41,8 @@ class String
41
41
  def mustard; colorize(self, "\e[1;35m"); end
42
42
  def cyan; colorize(self, "\e[0;36m"); end
43
43
  def cyan2; colorize(self, "\e[1;36m"); end
44
+ def light_gray; colorize(self, "\e[2;37m"); end
45
+ def bright_red; colorize(self, "\e[1;41m"); end
44
46
  def white; colorize(self, "\e[0;97m"); end
45
47
  def on_black; colorize(self, "\e[40m"); end
46
48
  def on_red; colorize(self, "\e[41m"); end
@@ -1,8 +1,8 @@
1
1
  # encoding: UTF-8
2
2
  #
3
- # Author: Stefano Harding <riddopic@gmail.com>
4
- #
5
- # Copyright (C) 2014-2015 Stefano Harding
3
+ # Author: Stefano Harding <riddopic@gmail.com>
4
+ # License: Apache License, Version 2.0
5
+ # Copyright: (C) 2014-2015 Stefano Harding
6
6
  #
7
7
  # Licensed under the Apache License, Version 2.0 (the "License");
8
8
  # you may not use this file except in compliance with the License.
@@ -17,6 +17,7 @@
17
17
  # limitations under the License.
18
18
  #
19
19
 
20
+
20
21
  # Add #try and #try!
21
22
  class Object
22
23
  # Invokes the public method whose name goes as first argument just like
@@ -1,3 +1,21 @@
1
+ # encoding: UTF-8
2
+ #
3
+ # Author: Stefano Harding <riddopic@gmail.com>
4
+ # License: Apache License, Version 2.0
5
+ # Copyright: (C) 2014-2015 Stefano Harding
6
+ #
7
+ # Licensed under the Apache License, Version 2.0 (the "License");
8
+ # you may not use this file except in compliance with the License.
9
+ # You may obtain a copy of the License at
10
+ #
11
+ # http://www.apache.org/licenses/LICENSE-2.0
12
+ #
13
+ # Unless required by applicable law or agreed to in writing, software
14
+ # distributed under the License is distributed on an "AS IS" BASIS,
15
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
+ # See the License for the specific language governing permissions and
17
+ # limitations under the License.
18
+ #
1
19
 
2
20
  require 'set'
3
21
 
@@ -1,4 +1,21 @@
1
1
  # encoding: UTF-8
2
+ #
3
+ # Author: Stefano Harding <riddopic@gmail.com>
4
+ # License: Apache License, Version 2.0
5
+ # Copyright: (C) 2014-2015 Stefano Harding
6
+ #
7
+ # Licensed under the Apache License, Version 2.0 (the "License");
8
+ # you may not use this file except in compliance with the License.
9
+ # You may obtain a copy of the License at
10
+ #
11
+ # http://www.apache.org/licenses/LICENSE-2.0
12
+ #
13
+ # Unless required by applicable law or agreed to in writing, software
14
+ # distributed under the License is distributed on an "AS IS" BASIS,
15
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
+ # See the License for the specific language governing permissions and
17
+ # limitations under the License.
18
+ #
2
19
 
3
20
  Hoodie::Inflections.inflections do |inflect|
4
21
  inflect.plural(/$/, 's')
@@ -1,4 +1,21 @@
1
1
  # encoding: UTF-8
2
+ #
3
+ # Author: Stefano Harding <riddopic@gmail.com>
4
+ # License: Apache License, Version 2.0
5
+ # Copyright: (C) 2014-2015 Stefano Harding
6
+ #
7
+ # Licensed under the Apache License, Version 2.0 (the "License");
8
+ # you may not use this file except in compliance with the License.
9
+ # You may obtain a copy of the License at
10
+ #
11
+ # http://www.apache.org/licenses/LICENSE-2.0
12
+ #
13
+ # Unless required by applicable law or agreed to in writing, software
14
+ # distributed under the License is distributed on an "AS IS" BASIS,
15
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
+ # See the License for the specific language governing permissions and
17
+ # limitations under the License.
18
+ #
2
19
 
3
20
  module Hoodie
4
21
  module Inflections
@@ -1,4 +1,21 @@
1
1
  # encoding: UTF-8
2
+ #
3
+ # Author: Stefano Harding <riddopic@gmail.com>
4
+ # License: Apache License, Version 2.0
5
+ # Copyright: (C) 2014-2015 Stefano Harding
6
+ #
7
+ # Licensed under the Apache License, Version 2.0 (the "License");
8
+ # you may not use this file except in compliance with the License.
9
+ # You may obtain a copy of the License at
10
+ #
11
+ # http://www.apache.org/licenses/LICENSE-2.0
12
+ #
13
+ # Unless required by applicable law or agreed to in writing, software
14
+ # distributed under the License is distributed on an "AS IS" BASIS,
15
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
+ # See the License for the specific language governing permissions and
17
+ # limitations under the License.
18
+ #
2
19
 
3
20
  module Hoodie
4
21
  module Inflections
@@ -1,8 +1,8 @@
1
1
  # encoding: UTF-8
2
2
  #
3
- # Author: Stefano Harding <riddopic@gmail.com>
4
- #
5
- # Copyright (C) 2014-2015 Stefano Harding
3
+ # Author: Stefano Harding <riddopic@gmail.com>
4
+ # License: Apache License, Version 2.0
5
+ # Copyright: (C) 2014-2015 Stefano Harding
6
6
  #
7
7
  # Licensed under the Apache License, Version 2.0 (the "License");
8
8
  # you may not use this file except in compliance with the License.
@@ -17,6 +17,7 @@
17
17
  # limitations under the License.
18
18
  #
19
19
 
20
+ require 'hoodie/core_ext/string'
20
21
  require 'logger'
21
22
  require 'time'
22
23
 
@@ -95,7 +96,7 @@ module Hoodie
95
96
  def call(severity, time, progname, msg)
96
97
  format % [
97
98
  format_datetime(time).blue,
98
- severity.green,
99
+ format_severity(severity),
99
100
  msg2str(msg).strip.orange
100
101
  ]
101
102
  end
@@ -106,6 +107,23 @@ module Hoodie
106
107
  "[%s] %5s: %s\n"
107
108
  end
108
109
 
110
+ def format_severity(severity)
111
+ case severity
112
+ when 'FATAL'
113
+ severity.bright_red
114
+ when 'ERROR'
115
+ severity.red
116
+ when 'WARN'
117
+ severity.yellow
118
+ when 'DEBUG'
119
+ severity.light_gray
120
+ when 'INFO'
121
+ severity.green
122
+ else
123
+ severity
124
+ end
125
+ end
126
+
109
127
  def format_datetime(time)
110
128
  if @datetime_format.nil?
111
129
  time.strftime("%Y-%m-%dT%H:%M:%S.") << "%06d " % time.usec
@@ -1,8 +1,8 @@
1
1
  # encoding: UTF-8
2
2
  #
3
- # Author: Stefano Harding <riddopic@gmail.com>
4
- #
5
- # Copyright (C) 2014 Stefano Harding
3
+ # Author: Stefano Harding <riddopic@gmail.com>
4
+ # License: Apache License, Version 2.0
5
+ # Copyright: (C) 2014-2015 Stefano Harding
6
6
  #
7
7
  # Licensed under the Apache License, Version 2.0 (the "License");
8
8
  # you may not use this file except in compliance with the License.
@@ -17,102 +17,105 @@
17
17
  # limitations under the License.
18
18
  #
19
19
 
20
- require 'hoodie/stash/disk_store' unless defined?(DiskStash)
21
- require 'hoodie/stash/mem_store' unless defined?(MemStash)
22
- require 'hoodie/memoizable' unless defined?(Memoizable)
20
+ require 'hoodie/stash/disk_stash'
21
+ require 'hoodie/stash/mem_stash'
22
+ require 'hoodie/stash/memoizable'
23
+ require 'hoodie/utils/os'
23
24
 
24
- # Define the basic cache and default store objects
25
- module Stash
26
- # check if we're using a version if Ruby that supports caller_locations
27
- NEW_CALL = Kernel.respond_to? 'caller_locations'
25
+ module Hoodie
26
+ # Define the basic cache and default store objects
27
+ #
28
+ module Stash
29
+ # check if we're using a version if Ruby that supports caller_locations
30
+ NEW_CALL = Kernel.respond_to? 'caller_locations'
28
31
 
29
- class << self
30
32
  # insert a helper .new() method for creating a new object
31
33
  #
32
- def new(*args)
34
+ def self.new(*args)
33
35
  self::Cache.new(*args)
34
36
  end
35
37
 
36
38
  # helper to get the calling function name
37
39
  #
38
- def caller_name
40
+ def self.caller_name
39
41
  NEW_CALL ? caller_locations(2, 1).first.label : caller[1][/`([^']*)'/, 1]
40
42
  end
41
- end
42
43
 
43
- # Default store type
44
- DEFAULT_STORE = MemStash::Cache
44
+ # Default store type
45
+ DEFAULT_STORE = MemStash
45
46
 
46
- # Key/value cache store
47
- class Cache
48
- # @return [Hash] of the mem stash cache hash store
49
- #
50
- attr_reader :store
47
+ # Key/value cache store
48
+ class Cache
51
49
 
52
- # Initializes a new empty store
53
- #
54
- def initialize(params = {})
55
- params = { store: params } unless params.is_a? Hash
56
- @store = params.fetch(:store) { Stash::DEFAULT_STORE.new }
57
- end
50
+ # @!attribute [r] :store
51
+ # @return [Stash::DiskStore] location of Stash::DiskStore store.
52
+ attr_reader :store
58
53
 
59
- # Clear the whole stash store or the value of a key
60
- #
61
- # @param key [Symbol, String] (optional) representing the key to
62
- # clear.
63
- #
64
- # @return nothing.
65
- #
66
- def clear!(key = nil)
67
- key = key.to_sym unless key.nil?
68
- @store.clear! key
69
- end
54
+ # Initializes a new empty store
55
+ #
56
+ def initialize(params = {})
57
+ params = { store: params } unless params.is_a? Hash
58
+ @store = params.fetch(:store) { Hoodie::DEFAULT_STORE.new }
59
+ end
70
60
 
71
- # Retrieves the value for a given key, if nothing is set,
72
- # returns KeyError
73
- #
74
- # @param key [Symbol, String] representing the key
75
- #
76
- # @raise [KeyError] if no such key found
77
- #
78
- # @return [Hash, Array, String] value for key
79
- #
80
- def [](key = nil)
81
- key ||= Stash.caller_name
82
- fail KeyError, 'Key not cached' unless include? key.to_sym
83
- @store[key.to_sym]
84
- end
61
+ # Clear the whole stash store or the value of a key
62
+ #
63
+ # @param key [Symbol, String] (optional) representing the key to
64
+ # clear.
65
+ #
66
+ # @return nothing.
67
+ #
68
+ def clear!(key = nil)
69
+ key = key.to_sym unless key.nil?
70
+ @store.clear! key
71
+ end
85
72
 
86
- # Retrieves the value for a given key, if nothing is set,
87
- # run the code, cache the result, and return it
88
- #
89
- # @param key [Symbol, String] representing the key
90
- # @param block [&block] that returns the value to set (optional)
91
- #
92
- # @return [Hash, Array, String] value for key
93
- #
94
- def cache(key = nil, &code)
95
- key ||= Stash.caller_name
96
- @store[key.to_sym] ||= code.call
97
- end
73
+ # Retrieves the value for a given key, if nothing is set,
74
+ # returns KeyError
75
+ #
76
+ # @param key [Symbol, String] representing the key
77
+ #
78
+ # @raise [KeyError] if no such key found
79
+ #
80
+ # @return [Hash, Array, String] value for key
81
+ #
82
+ def [](key = nil)
83
+ key ||= Stash.caller_name
84
+ fail KeyError, 'Key not cached' unless include? key.to_sym
85
+ @store[key.to_sym]
86
+ end
98
87
 
99
- # return the size of the store as an integer
100
- #
101
- # @return [Fixnum]
102
- #
103
- def size
104
- @store.size
105
- end
88
+ # Retrieves the value for a given key, if nothing is set,
89
+ # run the code, cache the result, and return it
90
+ #
91
+ # @param key [Symbol, String] representing the key
92
+ # @param block [&block] that returns the value to set (optional)
93
+ #
94
+ # @return [Hash, Array, String] value for key
95
+ #
96
+ def cache(key = nil, &code)
97
+ key ||= Stash.caller_name
98
+ @store[key.to_sym] ||= code.call
99
+ end
106
100
 
107
- # return a boolean indicating presence of the given key in the store
108
- #
109
- # @param key [Symbol, String] a string or symbol representing the key
110
- #
111
- # @return [TrueClass, FalseClass]
112
- #
113
- def include?(key = nil)
114
- key ||= Stash.caller_name
115
- @store.include? key.to_sym
101
+ # return the size of the store as an integer
102
+ #
103
+ # @return [Fixnum]
104
+ #
105
+ def size
106
+ @store.size
107
+ end
108
+
109
+ # return a boolean indicating presence of the given key in the store
110
+ #
111
+ # @param key [Symbol, String] a string or symbol representing the key
112
+ #
113
+ # @return [Boolean]
114
+ #
115
+ def include?(key = nil)
116
+ key ||= Stash.caller_name
117
+ @store.include? key.to_sym
118
+ end
116
119
  end
117
120
  end
118
121
  end
@@ -1,8 +1,8 @@
1
1
  # encoding: UTF-8
2
2
  #
3
- # Author: Stefano Harding <riddopic@gmail.com>
4
- #
5
- # Copyright (C) 2014-2015 Stefano Harding
3
+ # Author: Stefano Harding <riddopic@gmail.com>
4
+ # License: Apache License, Version 2.0
5
+ # Copyright: (C) 2014-2015 Stefano Harding
6
6
  #
7
7
  # Licensed under the Apache License, Version 2.0 (the "License");
8
8
  # you may not use this file except in compliance with the License.
@@ -12,140 +12,164 @@
12
12
  #
13
13
  # Unless required by applicable law or agreed to in writing, software
14
14
  # distributed under the License is distributed on an "AS IS" BASIS,
15
- # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
16
- # implied. See the License for the specific language governing
17
- # permissions and limitations under the License.
15
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
+ # See the License for the specific language governing permissions and
17
+ # limitations under the License.
18
18
  #
19
19
 
20
20
  require 'tmpdir'
21
21
 
22
- module DiskStash
22
+ module Hoodie
23
23
  # Disk stashing method variable caching hash, string, array store.
24
- class Cache
25
- include Enumerable
26
-
27
- # @return [String] location of DiskStash::Cache.store
28
- #
29
- attr_reader :store
30
-
31
- # Initializes a new disked backed stash hash cache store.
32
- #
33
- # @param path [String] location for stash store cache.
34
- #
35
- # @return nothing.
36
- #
37
- def initialize(store = file_store)
38
- @store = store
39
- _ensure_store_directory
40
- end
24
+ #
25
+ class Stash
26
+ class DiskStash
27
+
28
+ # @!attribute [r] :store
29
+ # @return [Stash::DiskStore] location of Stash::DiskStore store.
30
+ attr_reader :store
31
+
32
+ # Initializes a new disked backed stash hash cache store.
33
+ #
34
+ # @param path [String] location for stash store cache.
35
+ #
36
+ # @return nothing.
37
+ #
38
+ def initialize(store = file_store)
39
+ @store = store
40
+ end
41
+
42
+ # Retrieves a value from the cache, if available and not expired, or
43
+ # yields to a block that calculates the value to be stored in the cache.
44
+ #
45
+ # @param [Object] key
46
+ # The key to look up or store at.
47
+ #
48
+ # @yield yields when the value is not present.
49
+ #
50
+ # @yieldreturn [Object]
51
+ # The value to store in the cache.
52
+ #
53
+ # @return [Object]
54
+ # The value at the key.
55
+ #
56
+ def cache(key = nil, &code)
57
+ key ||= Stash.caller_name
58
+ @store[key.to_sym] ||= code.call
59
+ end
41
60
 
42
- # Clear the whole stash or the value of a key
43
- #
44
- # @param key [Symbol, String] (optional) string or symbol
45
- # representing the key to clear
46
- #
47
- # @return [Hash] with a key, return the value it had, without
48
- # returns {}
49
- #
50
- def clear!(key = nil)
51
- if key.nil?
52
- ::Dir[::File.join(store, '*.cache')].each do |file|
53
- ::File.delete(file)
61
+ # Clear the whole stash or the value of a key.
62
+ #
63
+ # @param [Symbol, String] key
64
+ # String or symbol representing the key to clear.
65
+ #
66
+ # @return [Hash]
67
+ # Previously stored Key/Value pair before the delete operation.
68
+ #
69
+ def clear!(key = nil)
70
+ if key.nil?
71
+ Dir[File.join(store, '*.cache')].each do |file|
72
+ File.delete(file)
73
+ end
74
+ else
75
+ File.delete(cache_file(key)) if File.exist?(cache_file(key))
54
76
  end
55
- else
56
- ::File.delete(cache_file(key)) if ::File.exist?(cache_file(key))
57
77
  end
58
- end
59
78
 
60
- # Retrieves the value for a given key, if nothing is set,
61
- # returns nil
62
- #
63
- # @param key [Symbol, String] representing the key
64
- #
65
- # @return [Hash, Array, String] value for key
66
- #
67
- def [](key)
68
- if key.is_a? Array
69
- hash = {}
70
- key.each do |k|
71
- hash[k] = Marshal.load(_read_cache_file(k))
79
+ # Retrieves the value for a given key, if nothing is set returns nil.
80
+ #
81
+ # @param [Symbol, String] key
82
+ # String or symbol representing the key.
83
+ #
84
+ # @return [Hash]
85
+ # The value for the key.
86
+ #
87
+ def [](key)
88
+ if key.is_a? Array
89
+ hash = {}
90
+ key.each do |k|
91
+ hash[k] = Marshal.load(read_cache_file(k))
92
+ end
93
+ hash unless hash.empty?
94
+ else
95
+ Marshal.load(read_cache_file(key))
72
96
  end
73
- hash unless hash.empty?
74
- else
75
- Marshal.load(_read_cache_file(key))
97
+ rescue Errno::ENOENT
98
+ nil # key hasn't been created
76
99
  end
77
- rescue Errno::ENOENT
78
- nil # key hasn't been created
79
- end
80
100
 
81
- # Store the given value with the given key, either an an argument
82
- # or block. If a previous value was set it will be overwritten
83
- # with the new value.
84
- #
85
- # @param key [Symbol, String] representing the key
86
- # @param value [Object] that represents the value (optional)
87
- # @param block [&block] that returns the value to set (optional)
88
- #
89
- # @return nothing.
90
- #
91
- def []=(key, value)
92
- _write_cache_file(key, Marshal.dump(value))
93
- end
101
+ # Store the given value with the given key, either an an argument or
102
+ # block. If a previous value was set it will be overwritten with the new
103
+ # value.
104
+ #
105
+ # @param [Symbol, String] key
106
+ # String or symbol representing the key.
107
+ #
108
+ # @param [Object] value
109
+ # That represents the value (optional)
110
+ #
111
+ # @param [&block] block
112
+ # That returns the value to set (optional)
113
+ #
114
+ # @return [undefined]
115
+ #
116
+ def []=(key, value)
117
+ write_cache_file(key, Marshal.dump(value))
118
+ end
94
119
 
95
- # returns path to cache file with 'key'
96
- def cache_file(key)
97
- ::File.join(store, key.to_s + '.cache')
98
- end
120
+ # returns path to cache file with 'key'
121
+ def cache_file(key)
122
+ File.join(store, key.to_s + '.cache')
123
+ end
99
124
 
100
- private # P R O P R I E T À P R I V A T A divieto di accesso
101
-
102
- # return Chef tmpfile path if running under Chef, else return OS
103
- # temp path. On Winders Dir.tmpdir returns the correct path.
104
- #
105
- def file_store
106
- if OS.windows?
107
- win_friendly_path('/chef/._stash_')
108
- elsif OS.mac?
109
- ::File.join(::File::SEPARATOR, 'var', 'tmp', '._stash')
110
- else
111
- ::File.join(::File::SEPARATOR, 'var', 'lib', '._stash')
125
+ private # P R O P R I E T À P R I V A T A divieto di accesso
126
+
127
+ def file_store
128
+ if Hoodie::OS.windows?
129
+ win_friendly_path('/chef/._stash_')
130
+ elsif Hoodie::OS.mac?
131
+ File.join(File::SEPARATOR, 'var', 'tmp', '._stash')
132
+ else
133
+ File.join(File::SEPARATOR, 'var', 'lib', '._stash')
134
+ end
112
135
  end
113
- end
114
136
 
115
- # returns windows friendly version of the provided path, ensures
116
- # backslashes are used everywhere
117
- #
118
- def win_friendly_path(path)
119
- system_drive = ENV['SYSTEMDRIVE'] ? ENV['SYSTEMDRIVE'] : ''
120
- path = ::File.join(system_drive, path)
121
- path.gsub!(::File::SEPARATOR, (::File::ALT_SEPARATOR || '\\'))
122
- end
137
+ # returns windows friendly version of the provided path, ensures
138
+ # backslashes are used everywhere
139
+ #
140
+ def win_friendly_path(path)
141
+ system_drive = ENV['SYSTEMDRIVE'] ? ENV['SYSTEMDRIVE'] : ''
142
+ path = File.join(system_drive, path)
143
+ path.gsub!(File::SEPARATOR, (File::ALT_SEPARATOR || '\\'))
144
+ end
123
145
 
124
- def _write_cache_file(key, content)
125
- mode = OS.windows? ? 'wb' : 'w+'
126
- f = ::File.open(cache_file(key), mode)
127
- f.flock(::File::LOCK_EX)
128
- f.write(content)
129
- f.close
130
- content
131
- end
146
+ def write_cache_file(key, content)
147
+ mode = OS.windows? ? 'wb' : 'w+'
148
+ file = File.open(cache_file(key), mode)
149
+ ensure_enclosing_dir(File.dirname file)
150
+ file.flock(File::LOCK_EX)
151
+ file.write(content)
152
+ file.close
153
+ content
154
+ end
132
155
 
133
- def _read_cache_file(key)
134
- mode = OS.windows? ? 'rb' : 'r'
135
- f = ::File.open(cache_file(key), mode)
136
- f.flock(::File::LOCK_SH)
137
- out = f.read
138
- f.close
139
- out
140
- end
156
+ def read_cache_file(key)
157
+ mode = OS.windows? ? 'rb' : 'r'
158
+ f = File.open(cache_file(key), mode)
159
+ f.flock(File::LOCK_SH)
160
+ out = f.read
161
+ f.close
162
+ out
163
+ end
141
164
 
142
- def read_cache_mtime(key)
143
- nil unless ::File.exist?(cache_file(key))
144
- ::File.mtime(cache_file(key))
145
- end
165
+ def read_cache_mtime(key)
166
+ nil unless File.exist?(cache_file(key))
167
+ File.mtime(cache_file(key))
168
+ end
146
169
 
147
- def _ensure_store_directory
148
- ::Dir.mkdir(store) unless ::File.directory?(store)
149
- end
170
+ def ensure_enclosing_dir(dir)
171
+ FileUtils.mkdir_p(file_store) unless File.directory?(dir)
172
+ end
173
+ end
150
174
  end
151
175
  end