sugar_utils 0.2.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: c614940d4ed952e41a7b52798188e3a0ac39a983
4
- data.tar.gz: f5ddaf4709df842179c3d85f1b4abdf67c39c636
3
+ metadata.gz: 4b841240e219afa9f5e780a7c3bd9ae389916c48
4
+ data.tar.gz: fbb71eb94aaac991e157b215d3eb38c4af935fe2
5
5
  SHA512:
6
- metadata.gz: e09c44845626a114fbacc8a9a8ba82db43abf86d40951eaf4e880d1779469459407cc020c6861a278dbee23f2cbe1cae8f0bbcb64f137e97965b51dc913f3332
7
- data.tar.gz: 64f9577e97eafbd53f4b9f8c2a8d8bdd114677bfbd2b73c45e9564bbc5245f9a665271f4bc32db4829094e74f9a12ffcc9b07033bf8f331c002ee2b566e10523
6
+ metadata.gz: fe6d9af436894005aed3882bc59387d5bb240a50780d32c1e0de9cc1443d8bbfac9ec146076a9a15d5d49d5abf80e736220f506de2ec30ed2db6a74a930fdf81
7
+ data.tar.gz: eaf877c2a627817cc6f89837c51a35c89641abb6346633c6c74759a94242001c6dcc9021d5aca0a984111791d0527a610949d985192a1979edbd239ffbca6b31
data/.rubocop.yml CHANGED
@@ -1,2 +1,17 @@
1
1
  Documentation:
2
2
  Enabled: false
3
+
4
+ Metrics/LineLength:
5
+ Max: 90
6
+
7
+ Metrics/MethodLength:
8
+ Max: 20
9
+
10
+ Metrics/AbcSize:
11
+ Max: 19
12
+
13
+ # Because of the way that blocks are used in RSpecs can end up being long when
14
+ # example groups are nested or many examples are checked.
15
+ Metrics/BlockLength:
16
+ Exclude:
17
+ - 'spec/**/*'
data/.travis.yml CHANGED
@@ -3,8 +3,15 @@ rvm:
3
3
  - 2.0
4
4
  - 2.1
5
5
  - 2.2
6
+ - 2.3.3
7
+ - 2.4.0
6
8
  - ruby-head
7
9
  matrix:
8
10
  allow_failures:
9
11
  - rvm: ruby-head
10
12
  sudo: false
13
+ addons:
14
+ code_climate:
15
+ repo_token: c250bc1551dd13a07efdd5bc8a594924f6f762f7be9762e79da0c8f065cf93dd
16
+ after_success:
17
+ - bundle exec codeclimate-test-reporter
data/CHANGELOG.md CHANGED
@@ -2,6 +2,17 @@
2
2
  All notable changes to this project will be documented in this file.
3
3
  This project adheres to [Semantic Versioning](http://semver.org/).
4
4
 
5
+ ## [0.3.0] - 2017-03-29
6
+ ### Added
7
+ - SugarUtils::File.read, with locking and error handling when reading a plain
8
+ text file
9
+ - SugarUtils::File.write, with locking and error handling when writing a plain
10
+ text file
11
+
12
+ ### Changed
13
+ - explicitly specify the Ruby v2.0.0 support limit
14
+ - divide SugarUtils::File.flock into .flock_shared and .flock_exclusive
15
+
5
16
  ## [0.2.0] - 2016-07-21
6
17
  ### Added
7
18
  - SugarUtils::File.flock, for file locking with a timeout
data/README.md CHANGED
@@ -3,8 +3,8 @@
3
3
  [![Gem Version](https://badge.fury.io/rb/sugar_utils.svg)](http://badge.fury.io/rb/sugar_utils)
4
4
  [![Dependency Status](https://gemnasium.com/sugarcrm/sugar_utils.svg)](https://gemnasium.com/sugarcrm/sugar_utils)
5
5
  [![Build Status](https://travis-ci.org/sugarcrm/sugar_utils.svg?branch=master)](https://travis-ci.org/sugarcrm/sugar_utils)
6
- [![Coverage Status](http://img.shields.io/coveralls/sugarcrm/sugar_utils/master.svg)](https://coveralls.io/r/sugarcrm/sugar_utils)
7
6
  [![Code Climate](https://codeclimate.com/github/sugarcrm/sugar_utils/badges/gpa.svg)](https://codeclimate.com/github/sugarcrm/sugar_utils)
7
+ [![Test Coverage](https://codeclimate.com/github/sugarcrm/sugar_utils/badges/coverage.svg)](https://codeclimate.com/github/sugarcrm/sugar_utils/coverage)
8
8
  [![Inline docs](http://inch-ci.org/github/sugarcrm/sugar_utils.svg)](http://inch-ci.org/github/sugarcrm/sugar_utils)
9
9
  [![License](http://img.shields.io/badge/license-Apache2-green.svg?style=flat)](LICENSE)
10
10
 
@@ -12,16 +12,20 @@ Utility methods extracted from SugarCRM Ruby projects.
12
12
 
13
13
  These methods are included:
14
14
 
15
- * ensure_boolean
16
- * ensure_integer
15
+ * SugarUtils.ensure_boolean
16
+ * SugarUtils.ensure_integer
17
+ * SugarUtils::File.flock_shared
18
+ * SugarUtils::File.flock_exclusive
19
+ * SugarUtils::File.read
20
+ * SugarUtils::File.write
21
+ * SugarUtils::File.read_json
22
+ * SugarUtils::File.write_json
17
23
 
18
24
  These methods will probably be included in the future:
19
25
 
20
26
  * sizeof_dir
21
27
  * find_files
22
28
  * find_file!
23
- * read_json
24
- * write_json
25
29
  * gzip
26
30
  * gunzip
27
31
  * tarball
@@ -30,7 +34,6 @@ These methods will probably be included in the future:
30
34
  * encrypt
31
35
  * http_get_file
32
36
  * timeout_retry
33
- * flock_with_timeout
34
37
 
35
38
  ## Installation
36
39
 
@@ -44,7 +47,7 @@ gem 'sugar_utils'
44
47
  And then execute:
45
48
 
46
49
  ```bash
47
- $ bundle
50
+ $ bundle install
48
51
  ```
49
52
 
50
53
  Or install it yourself as:
data/Rakefile CHANGED
@@ -1,4 +1,5 @@
1
1
  # -*- encoding: utf-8 -*-
2
+
2
3
  require 'bundler/gem_tasks'
3
4
  require 'rspec/core/rake_task'
4
5
  require 'rubocop/rake_task'
@@ -22,6 +23,6 @@ Yardstick::Rake::Measurement.new(:yardstick_measure) do |measurement|
22
23
  measurement.output = 'tmp/yard_coverage.txt'
23
24
  end
24
25
 
25
- task quality: [:rubocop, :yardstick_measure]
26
+ task quality: %i(rubocop yardstick_measure)
26
27
 
27
28
  task default: [:spec]
@@ -3,77 +3,101 @@
3
3
  require 'solid_assert'
4
4
  require 'fileutils'
5
5
  require 'multi_json'
6
+ require 'timeout'
6
7
 
7
8
  module SugarUtils
8
9
  module File
9
10
  class Error < StandardError; end
10
11
 
11
- # flock with a timeout to ensure that it does not flock forever.
12
+ # @param [File] file
13
+ # @param [Hash] options
14
+ # @option options [Integer] :timeout (10)
12
15
  #
13
- # @see http://www.codegnome.com/blog/2013/05/26/locking-files-with-ruby/
16
+ # @raise [Timeout::Error]
14
17
  #
18
+ # @return [void]
19
+ def self.flock_shared(file, options = {})
20
+ timeout = options[:timeout] || 10
21
+ Timeout.timeout(timeout) { file.flock(::File::LOCK_SH) }
22
+ end
23
+
15
24
  # @param [File] file
16
- # @param [File::LOCK_EX, File::LOCK_SH] locking_constant
17
25
  # @param [Hash] options
18
26
  # @option options [Integer] :timeout (10)
19
27
  #
28
+ # @raise [Timeout::Error]
29
+ #
20
30
  # @return [void]
21
- def self.flock(file, locking_constant, options = {})
31
+ def self.flock_exclusive(file, options = {})
22
32
  timeout = options[:timeout] || 10
23
- Timeout.timeout(timeout) { file.flock(locking_constant) }
33
+ Timeout.timeout(timeout) { file.flock(::File::LOCK_EX) }
24
34
  end
25
35
 
26
36
  # @param [String] filename
27
37
  # @param [Hash] options
28
38
  # @option options [Integer] :timeout (10)
29
39
  # @option options [Boolean] :raise_on_missing (true)
40
+ # @option options [String] :value_on_missing ('') which specifies the
41
+ # value to return if the file is missing and raise_on_missing is false
30
42
  #
31
- # @raise [SugarUtils::File::Error)
43
+ # @raise [SugarUtils::File::Error]
32
44
  #
33
- # @return [Object]
34
- def self.read_json(filename, options = {})
35
- assert(options.is_a?(Hash), 'options MUST be a Hash')
36
-
45
+ # @return [String]
46
+ def self.read(filename, options = {})
47
+ options[:value_on_missing] ||= ''
37
48
  options[:raise_on_missing] = true if options[:raise_on_missing].nil?
38
49
 
39
50
  ::File.open(filename, ::File::RDONLY) do |file|
40
- flock(file, ::File::LOCK_SH, options)
41
- MultiJson.load(file.read)
51
+ flock_shared(file, options)
52
+ file.read
42
53
  end
43
54
  rescue SystemCallError, IOError
44
55
  raise(Error, "Cannot read #{filename}") if options[:raise_on_missing]
45
- {}
46
- rescue MultiJson::ParseError
47
- raise(Error, "Cannot parse #{filename}")
56
+ options[:value_on_missing]
48
57
  rescue Timeout::Error
49
58
  raise(Error, "Cannot read #{filename} because it is locked")
50
59
  end
51
60
 
52
61
  # @param [String] filename
53
- # @param [#to_json] data
62
+ # @param [Hash] options
63
+ # @option options [Integer] :timeout (10)
64
+ # @option options [Boolean] :raise_on_missing (true)
65
+ #
66
+ # @raise [SugarUtils::File::Error]
67
+ #
68
+ # @return [Object]
69
+ def self.read_json(filename, options = {})
70
+ options[:value_on_missing] = {}
71
+ MultiJson.load(read(filename, options))
72
+ rescue MultiJson::ParseError
73
+ raise(Error, "Cannot parse #{filename}")
74
+ end
75
+
76
+ # @param [String] filename
77
+ # @param [#to_s] data
54
78
  # @param [Hash] options
55
79
  # @option options [Integer] :timeout (10)
56
80
  # @option options [Boolean] :flush (false)
57
81
  # @option options [Integer] :perm (0666)
58
82
  #
59
- # @raise [SugarUtils::File::Error)
83
+ # @raise [SugarUtils::File::Error]
60
84
  #
61
85
  # @return [void]
62
- def self.write_json(filename, data, options = {})
63
- perm = options[:perm] || 0666
86
+ def self.write(filename, data, options = {})
87
+ perm = options[:perm] || 0o666
64
88
  flush = options[:flush] || false
65
89
 
66
90
  FileUtils.mkdir_p(::File.dirname(filename))
67
91
  ::File.open(filename, ::File::RDWR | ::File::CREAT, perm) do |file|
68
- flock(file, ::File::LOCK_EX, options)
92
+ flock_exclusive(file, options)
69
93
 
70
94
  file.truncate(0) # Ensure file is empty before proceeding.
71
- file.puts(MultiJson.dump(data, pretty: true))
95
+ file.puts(data.to_s)
72
96
 
73
97
  # Flush and fsync to be 100% sure we write this data out now because we
74
98
  # are often reading it immediately and if the OS is buffering, it is
75
- # possible we might read it before it is been physically written to disk.
76
- # We are not worried about speed here, so this should be OKAY.
99
+ # possible we might read it before it is been physically written to
100
+ # disk. We are not worried about speed here, so this should be OKAY.
77
101
  if flush
78
102
  file.flush
79
103
  file.fsync
@@ -87,5 +111,19 @@ module SugarUtils
87
111
  rescue SystemCallError, IOError => boom
88
112
  raise(Error, "Unable to write #{filename} with #{boom}")
89
113
  end
114
+
115
+ # @param [String] filename
116
+ # @param [#to_json] data
117
+ # @param [Hash] options
118
+ # @option options [Integer] :timeout (10)
119
+ # @option options [Boolean] :flush (false)
120
+ # @option options [Integer] :perm (0666)
121
+ #
122
+ # @raise [SugarUtils::File::Error]
123
+ #
124
+ # @return [void]
125
+ def self.write_json(filename, data, options = {})
126
+ write(filename, MultiJson.dump(data, pretty: true), options)
127
+ end
90
128
  end
91
129
  end
@@ -1,5 +1,5 @@
1
1
  # -*- encoding : utf-8 -*-
2
2
 
3
3
  module SugarUtils
4
- VERSION = '0.2.0'.freeze
4
+ VERSION = '0.3.0'.freeze
5
5
  end
data/spec/spec_helper.rb CHANGED
@@ -2,13 +2,54 @@
2
2
 
3
3
  $LOAD_PATH.unshift File.expand_path('../../lib', __FILE__)
4
4
  require 'sugar_utils'
5
- require 'simplecov'
6
5
  require 'rspec/tabular'
7
6
  require 'fakefs/spec_helpers'
8
- SimpleCov.start 'rails'
7
+ # HACK: including pp seems to resolve an error with FakeFS and File.read
8
+ # This seems to be related to but not the same as the problem mentioned in the
9
+ # README
10
+ # https://github.com/fakefs/fakefs#fakefs-vs-pp-----typeerror-superclass-mismatch-for-class-file
11
+ require 'pp'
12
+
13
+ # Setup code coverage
14
+ require 'simplecov'
15
+ SimpleCov.start
9
16
 
10
17
  SolidAssert.enable_assertions
11
18
 
12
19
  RSpec.configure do |config|
20
+ # rubocop:disable Style/MixinGrouping
13
21
  config.include FakeFS::SpecHelpers, fakefs: true
22
+ # rubocop:enable all
23
+ end
24
+
25
+ RSpec::Matchers.define :have_json_content do |expected|
26
+ match do |actual|
27
+ next false unless File.exist?(actual)
28
+
29
+ @actual = MultiJson.load(File.read(actual))
30
+ values_match?(expected, @actual)
31
+ end
32
+
33
+ diffable
34
+ end
35
+
36
+ RSpec::Matchers.define :have_content do |expected|
37
+ match do |actual|
38
+ next false unless File.exist?(actual)
39
+
40
+ @actual = File.open(actual, 'r') { |f| f.read.chomp }
41
+ values_match?(expected, @actual)
42
+ end
43
+
44
+ diffable
45
+ end
46
+
47
+ RSpec::Matchers.define :have_file_permission do |expected|
48
+ match do |actual|
49
+ next false unless File.exist?(actual)
50
+
51
+ @actual = format('%o', File.stat(filename).mode)
52
+ @expected = format('%o', expected)
53
+ values_match?(@expected, @actual)
54
+ end
14
55
  end
@@ -1,15 +1,14 @@
1
1
  # -*- encoding : utf-8 -*-
2
2
 
3
3
  require 'spec_helper'
4
- require 'fileutils'
5
4
 
6
5
  describe SugarUtils::File do
7
- describe '.flock' do
8
- subject { described_class.flock(file, :locking_constant, options) }
6
+ describe '.flock_shared' do
7
+ subject { described_class.flock_shared(file, options) }
9
8
  let(:file) { instance_double(File) }
10
9
  before do
11
- expect(Timeout).to receive(:timeout).with(expected_timeout).and_yield
12
- expect(file).to receive(:flock).with(:locking_constant)
10
+ allow(Timeout).to receive(:timeout).with(expected_timeout).and_yield
11
+ expect(file).to receive(:flock).with(::File::LOCK_SH)
13
12
  end
14
13
 
15
14
  inputs :options, :expected_timeout
@@ -18,59 +17,90 @@ describe SugarUtils::File do
18
17
  side_effects_with Hash[timeout: 5], 5
19
18
  end
20
19
 
21
- describe '.read_json', :fakefs do
22
- subject { described_class.read_json('filename.json', options) }
20
+ describe '.flock_exclusive' do
21
+ subject { described_class.flock_exclusive(file, options) }
22
+ let(:file) { instance_double(File) }
23
+ before do
24
+ allow(Timeout).to receive(:timeout).with(expected_timeout).and_yield
25
+ expect(file).to receive(:flock).with(::File::LOCK_EX)
26
+ end
23
27
 
24
- context 'missing file' do
28
+ inputs :options, :expected_timeout
29
+ side_effects_with Hash[], 10
30
+ side_effects_with Hash[timeout: nil], 10
31
+ side_effects_with Hash[timeout: 5], 5
32
+ end
33
+
34
+ describe '.read', :fakefs do
35
+ subject { described_class.read('filename', options) }
36
+
37
+ shared_examples_for 'handles the missing file error' do
38
+ # rubocop:disable Metrics/LineLength
25
39
  inputs :options
26
- raise_error_with Hash[], described_class::Error
27
- raise_error_with Hash[], 'Cannot read filename.json'
28
- raise_error_with Hash[raise_on_missing: true], described_class::Error
29
- raise_error_with Hash[raise_on_missing: true], 'Cannot read filename.json'
30
- it_with Hash[raise_on_missing: false], {}
40
+ raise_error_with Hash[], described_class::Error
41
+ raise_error_with Hash[], 'Cannot read filename'
42
+ raise_error_with Hash[raise_on_missing: true], described_class::Error
43
+ raise_error_with Hash[raise_on_missing: true], 'Cannot read filename'
44
+ it_with Hash[raise_on_missing: false], ''
45
+ it_with Hash[raise_on_missing: false, value_on_missing: 'hi'], 'hi'
46
+ # rubocop:enable all
31
47
  end
32
48
 
33
- context 'file present' do
34
- let(:options) { {} }
35
- before { write('filename.json', content) }
36
-
37
- context 'SysteCallError' do
38
- let(:options) { {} }
39
- let(:content) { '' }
40
- let(:exception) { SystemCallError.new(nil) }
41
- before { allow(File).to receive(:open).and_raise(exception) }
42
- it { expect_raise_error('Cannot read filename.json') }
43
- end
49
+ context 'missing file' do
50
+ it_behaves_like 'handles the missing file error'
51
+ end
44
52
 
45
- context 'IOError' do
46
- let(:options) { {} }
47
- let(:content) { '' }
48
- let(:exception) { IOError.new(nil) }
49
- before { allow(File).to receive(:open).and_raise(exception) }
50
- it { expect_raise_error('Cannot read filename.json') }
51
- end
53
+ context 'with IOError' do
54
+ before { allow(File).to receive(:open).and_raise(IOError) }
55
+ it_behaves_like 'handles the missing file error'
56
+ end
57
+
58
+ context 'file present' do
59
+ let(:options) { { key: :value } }
60
+ before { write('filename', 'content') }
52
61
 
53
62
  context 'and locked' do
54
- let(:content) { '' }
55
- before { expect_flock(File::LOCK_SH, options).and_raise(Timeout::Error) }
56
- it { expect_raise_error('Cannot read filename.json because it is locked') }
63
+ before do
64
+ expect(described_class).to receive(:flock_shared)
65
+ .with(kind_of(File), options)
66
+ .and_raise(Timeout::Error)
67
+ end
68
+ it { expect_raise_error('Cannot read filename because it is locked') }
57
69
  end
58
70
 
59
71
  context 'and unlocked' do
60
- before { expect_flock(File::LOCK_SH, options) }
61
-
62
- inputs :content
63
- raise_error_with 'I am not json', described_class::Error
64
- raise_error_with 'I am not json', 'Cannot parse filename.json'
65
- it_with Hash['key' => 'value'].to_json, Hash['key' => 'value']
72
+ before do
73
+ expect(described_class).to receive(:flock_shared)
74
+ .with(kind_of(File), options)
75
+ end
76
+ it { is_expected.to eq('content') }
66
77
  end
67
78
  end
68
79
  end
69
80
 
70
- describe '.write_json', :fakefs do
71
- subject { described_class.write_json(filename, data, options) }
72
- let(:data) { { 'key' => 'value' } }
73
- let(:filename) { 'dir1/dir2/filename.json' }
81
+ describe '.read_json', :fakefs do
82
+ subject do
83
+ described_class.read_json(
84
+ :filename, key: :value, value_on_missing: :foobar
85
+ )
86
+ end
87
+
88
+ before do
89
+ allow(described_class).to receive(:read)
90
+ .with(:filename, key: :value, value_on_missing: {})
91
+ .and_return(file_content)
92
+ end
93
+
94
+ inputs :file_content
95
+ raise_error_with 'I am not json', described_class::Error
96
+ raise_error_with 'I am not json', 'Cannot parse filename'
97
+ it_with Hash['key' => 'value'].to_json, Hash['key' => 'value']
98
+ end
99
+
100
+ describe '.write', :fakefs do
101
+ subject { described_class.write(filename, data, options) }
102
+ let(:data) { 'content' }
103
+ let(:filename) { 'dir1/dir2/filename' }
74
104
 
75
105
  context 'SystemCallError' do
76
106
  let(:options) { {} }
@@ -88,36 +118,37 @@ describe SugarUtils::File do
88
118
 
89
119
  context 'locked' do
90
120
  let(:options) { {} }
91
- before { expect_flock(File::LOCK_EX, options).and_raise(Timeout::Error) }
121
+ before do
122
+ expect(described_class).to receive(:flock_exclusive)
123
+ .with(kind_of(File), options)
124
+ .and_raise(Timeout::Error)
125
+ end
92
126
  it { expect_raise_error("Unable to write #{filename} because it is locked") }
93
127
  end
94
128
 
95
129
  context 'unlocked' do
96
130
  shared_examples_for 'file is written' do
97
- before { expect_flock(File::LOCK_EX, options) }
131
+ before do
132
+ expect(described_class).to receive(:flock_exclusive)
133
+ .with(kind_of(File), options)
134
+ end
98
135
 
99
136
  context 'default options' do
100
137
  let(:options) { {} }
101
138
  before { subject }
102
- specify do
103
- expect(File.exist?(filename)).to eq(true)
104
- expect(MultiJson.load(File.read(filename))).to eq(data)
105
- expect(sprintf('%o', File.stat(filename).mode)).to eq('100666')
106
- end
139
+ specify { expect(filename).to have_content(data) }
140
+ specify { expect(filename).to have_file_permission(0o100666) }
107
141
  end
108
142
 
109
143
  context 'options' do
110
- let(:options) { { flush: true, perm: 0600 } }
144
+ let(:options) { { flush: true, perm: 0o600 } }
111
145
  before do
112
146
  expect_any_instance_of(File).to receive(:flush)
113
147
  expect_any_instance_of(File).to receive(:fsync)
114
148
  subject
115
149
  end
116
- specify do
117
- expect(File.exist?(filename)).to eq(true)
118
- expect(MultiJson.load(File.read(filename))).to eq(data)
119
- expect(sprintf('%o', File.stat(filename).mode)).to eq('100600')
120
- end
150
+ specify { expect(filename).to have_content(data) }
151
+ specify { expect(filename).to have_file_permission(0o100600) }
121
152
  end
122
153
  end
123
154
 
@@ -126,7 +157,7 @@ describe SugarUtils::File do
126
157
  end
127
158
 
128
159
  context 'and exists' do
129
- before { write(filename, 'foobar', 0777) }
160
+ before { write(filename, 'foobar', 0o777) }
130
161
  context 'not locked' do
131
162
  it_behaves_like 'file is written'
132
163
  end
@@ -134,15 +165,21 @@ describe SugarUtils::File do
134
165
  end
135
166
  end
136
167
 
137
- ##############################################################################
168
+ describe '.write_json', :fakefs do
169
+ subject { described_class.write_json(:filename, data, :options) }
138
170
 
139
- # @param [File::LOCK_SH, File::LOCK_EX] locking_constant
140
- # @param [Hash] options
141
- def expect_flock(locking_constant, options)
142
- expect(described_class).to receive(:flock)
143
- .with(kind_of(File), locking_constant, options)
171
+ let(:data) { { 'key' => 'value' } }
172
+ before do
173
+ expect(described_class).to receive(:write).with(
174
+ :filename, MultiJson.dump(data, pretty: true), :options
175
+ )
176
+ end
177
+
178
+ specify { subject }
144
179
  end
145
180
 
181
+ ##############################################################################
182
+
146
183
  # @param [String] message
147
184
  def expect_raise_error(message)
148
185
  expect { subject }.to raise_error(described_class::Error, message)
@@ -163,6 +200,4 @@ describe SugarUtils::File do
163
200
  File.write(filename, content)
164
201
  FileUtils.chmod(perm, filename) if perm
165
202
  end
166
-
167
-
168
203
  end
data/sugar_utils.gemspec CHANGED
@@ -1,4 +1,5 @@
1
1
  # coding: utf-8
2
+
2
3
  lib = File.expand_path('../lib', __FILE__)
3
4
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
5
  require 'sugar_utils/version'
@@ -17,16 +18,19 @@ Gem::Specification.new do |spec|
17
18
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
18
19
  spec.require_paths = ['lib']
19
20
 
21
+ spec.required_ruby_version = '>= 2.0.0'
22
+
20
23
  spec.add_dependency 'multi_json', '~> 1.12.1'
21
24
  spec.add_dependency 'solid_assert', '~> 1.0'
22
25
 
23
26
  spec.add_development_dependency 'bundler', '~> 1.7'
24
- spec.add_development_dependency 'rake', '~> 10.0'
25
- spec.add_development_dependency 'rspec', '~> 3.4.0'
27
+ spec.add_development_dependency 'rake', '~> 12.0'
28
+ spec.add_development_dependency 'rspec', '~> 3.5.0'
26
29
  spec.add_development_dependency 'rspec-tabular', '~> 0.1.0'
27
- spec.add_development_dependency 'simplecov', '~> 0.11.0'
28
- spec.add_development_dependency 'rubocop', '~> 0.37'
29
- spec.add_development_dependency 'yard', '~> 0.8.7.6'
30
+ spec.add_development_dependency 'simplecov', '~> 0.14.0'
31
+ spec.add_development_dependency 'yard', '~> 0.9.0'
30
32
  spec.add_development_dependency 'yardstick', '~> 0.9.9'
31
33
  spec.add_development_dependency 'fakefs', '~> 0.7'
34
+ spec.add_development_dependency 'codeclimate-test-reporter'
35
+ spec.add_development_dependency 'rubocop'
32
36
  end
metadata CHANGED
@@ -1,169 +1,183 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sugar_utils
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andrew Sullivan Cant
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-07-21 00:00:00.000000000 Z
11
+ date: 2017-03-29 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: multi_json
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - ~>
17
+ - - "~>"
18
18
  - !ruby/object:Gem::Version
19
19
  version: 1.12.1
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - ~>
24
+ - - "~>"
25
25
  - !ruby/object:Gem::Version
26
26
  version: 1.12.1
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: solid_assert
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - ~>
31
+ - - "~>"
32
32
  - !ruby/object:Gem::Version
33
33
  version: '1.0'
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
- - - ~>
38
+ - - "~>"
39
39
  - !ruby/object:Gem::Version
40
40
  version: '1.0'
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: bundler
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
- - - ~>
45
+ - - "~>"
46
46
  - !ruby/object:Gem::Version
47
47
  version: '1.7'
48
48
  type: :development
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
- - - ~>
52
+ - - "~>"
53
53
  - !ruby/object:Gem::Version
54
54
  version: '1.7'
55
55
  - !ruby/object:Gem::Dependency
56
56
  name: rake
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
- - - ~>
59
+ - - "~>"
60
60
  - !ruby/object:Gem::Version
61
- version: '10.0'
61
+ version: '12.0'
62
62
  type: :development
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
- - - ~>
66
+ - - "~>"
67
67
  - !ruby/object:Gem::Version
68
- version: '10.0'
68
+ version: '12.0'
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: rspec
71
71
  requirement: !ruby/object:Gem::Requirement
72
72
  requirements:
73
- - - ~>
73
+ - - "~>"
74
74
  - !ruby/object:Gem::Version
75
- version: 3.4.0
75
+ version: 3.5.0
76
76
  type: :development
77
77
  prerelease: false
78
78
  version_requirements: !ruby/object:Gem::Requirement
79
79
  requirements:
80
- - - ~>
80
+ - - "~>"
81
81
  - !ruby/object:Gem::Version
82
- version: 3.4.0
82
+ version: 3.5.0
83
83
  - !ruby/object:Gem::Dependency
84
84
  name: rspec-tabular
85
85
  requirement: !ruby/object:Gem::Requirement
86
86
  requirements:
87
- - - ~>
87
+ - - "~>"
88
88
  - !ruby/object:Gem::Version
89
89
  version: 0.1.0
90
90
  type: :development
91
91
  prerelease: false
92
92
  version_requirements: !ruby/object:Gem::Requirement
93
93
  requirements:
94
- - - ~>
94
+ - - "~>"
95
95
  - !ruby/object:Gem::Version
96
96
  version: 0.1.0
97
97
  - !ruby/object:Gem::Dependency
98
98
  name: simplecov
99
99
  requirement: !ruby/object:Gem::Requirement
100
100
  requirements:
101
- - - ~>
101
+ - - "~>"
102
102
  - !ruby/object:Gem::Version
103
- version: 0.11.0
103
+ version: 0.14.0
104
104
  type: :development
105
105
  prerelease: false
106
106
  version_requirements: !ruby/object:Gem::Requirement
107
107
  requirements:
108
- - - ~>
108
+ - - "~>"
109
109
  - !ruby/object:Gem::Version
110
- version: 0.11.0
110
+ version: 0.14.0
111
111
  - !ruby/object:Gem::Dependency
112
- name: rubocop
112
+ name: yard
113
113
  requirement: !ruby/object:Gem::Requirement
114
114
  requirements:
115
- - - ~>
115
+ - - "~>"
116
116
  - !ruby/object:Gem::Version
117
- version: '0.37'
117
+ version: 0.9.0
118
118
  type: :development
119
119
  prerelease: false
120
120
  version_requirements: !ruby/object:Gem::Requirement
121
121
  requirements:
122
- - - ~>
122
+ - - "~>"
123
123
  - !ruby/object:Gem::Version
124
- version: '0.37'
124
+ version: 0.9.0
125
125
  - !ruby/object:Gem::Dependency
126
- name: yard
126
+ name: yardstick
127
127
  requirement: !ruby/object:Gem::Requirement
128
128
  requirements:
129
- - - ~>
129
+ - - "~>"
130
130
  - !ruby/object:Gem::Version
131
- version: 0.8.7.6
131
+ version: 0.9.9
132
132
  type: :development
133
133
  prerelease: false
134
134
  version_requirements: !ruby/object:Gem::Requirement
135
135
  requirements:
136
- - - ~>
136
+ - - "~>"
137
137
  - !ruby/object:Gem::Version
138
- version: 0.8.7.6
138
+ version: 0.9.9
139
139
  - !ruby/object:Gem::Dependency
140
- name: yardstick
140
+ name: fakefs
141
141
  requirement: !ruby/object:Gem::Requirement
142
142
  requirements:
143
- - - ~>
143
+ - - "~>"
144
144
  - !ruby/object:Gem::Version
145
- version: 0.9.9
145
+ version: '0.7'
146
146
  type: :development
147
147
  prerelease: false
148
148
  version_requirements: !ruby/object:Gem::Requirement
149
149
  requirements:
150
- - - ~>
150
+ - - "~>"
151
151
  - !ruby/object:Gem::Version
152
- version: 0.9.9
152
+ version: '0.7'
153
153
  - !ruby/object:Gem::Dependency
154
- name: fakefs
154
+ name: codeclimate-test-reporter
155
155
  requirement: !ruby/object:Gem::Requirement
156
156
  requirements:
157
- - - ~>
157
+ - - ">="
158
158
  - !ruby/object:Gem::Version
159
- version: '0.7'
159
+ version: '0'
160
160
  type: :development
161
161
  prerelease: false
162
162
  version_requirements: !ruby/object:Gem::Requirement
163
163
  requirements:
164
- - - ~>
164
+ - - ">="
165
165
  - !ruby/object:Gem::Version
166
- version: '0.7'
166
+ version: '0'
167
+ - !ruby/object:Gem::Dependency
168
+ name: rubocop
169
+ requirement: !ruby/object:Gem::Requirement
170
+ requirements:
171
+ - - ">="
172
+ - !ruby/object:Gem::Version
173
+ version: '0'
174
+ type: :development
175
+ prerelease: false
176
+ version_requirements: !ruby/object:Gem::Requirement
177
+ requirements:
178
+ - - ">="
179
+ - !ruby/object:Gem::Version
180
+ version: '0'
167
181
  description:
168
182
  email:
169
183
  - acant@sugarcrm.com
@@ -171,10 +185,10 @@ executables: []
171
185
  extensions: []
172
186
  extra_rdoc_files: []
173
187
  files:
174
- - .gitignore
175
- - .rspec
176
- - .rubocop.yml
177
- - .travis.yml
188
+ - ".gitignore"
189
+ - ".rspec"
190
+ - ".rubocop.yml"
191
+ - ".travis.yml"
178
192
  - CHANGELOG.md
179
193
  - CONTRIBUTING.md
180
194
  - CONTRIBUTOR_TERMS.md
@@ -199,17 +213,17 @@ require_paths:
199
213
  - lib
200
214
  required_ruby_version: !ruby/object:Gem::Requirement
201
215
  requirements:
202
- - - '>='
216
+ - - ">="
203
217
  - !ruby/object:Gem::Version
204
- version: '0'
218
+ version: 2.0.0
205
219
  required_rubygems_version: !ruby/object:Gem::Requirement
206
220
  requirements:
207
- - - '>='
221
+ - - ">="
208
222
  - !ruby/object:Gem::Version
209
223
  version: '0'
210
224
  requirements: []
211
225
  rubyforge_project:
212
- rubygems_version: 2.0.14.1
226
+ rubygems_version: 2.6.10
213
227
  signing_key:
214
228
  specification_version: 4
215
229
  summary: Utility methods extracted from SugarCRM Ruby projects.
@@ -217,4 +231,3 @@ test_files:
217
231
  - spec/spec_helper.rb
218
232
  - spec/sugar_utils/file_spec.rb
219
233
  - spec/sugar_utils_spec.rb
220
- has_rdoc: