sugar_utils 0.2.0 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
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: