strong_versions 0.2.0 → 0.2.1

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
  SHA256:
3
- metadata.gz: a9da34b3e4b80be8af4d27254850e051518efbf3073be7e13ab612e9ba9e8c75
4
- data.tar.gz: 42a655b38542c8b644b593cff388b91ade0229096165d0eba359eeef1a11cf22
3
+ metadata.gz: 1e9137c23cce3c8cf3ca835657b64fbfe74761fad58f14f9572020d5360dc4bf
4
+ data.tar.gz: 66e4f5b06fc23363b9a83016fcf2140006d124fef6813228d4cd6c6d8d4b5a1e
5
5
  SHA512:
6
- metadata.gz: 9002687db125d01a87f404cd27d6f855243c92b87813a44e44453804694735ba1292f5eb751751249ab8478b4efe845809f4739202f1069937830f73996dc4c7
7
- data.tar.gz: 616c683f92e0b1a0f8fcd8ac8b24a42bbd5dad96b2d1dbff5d7ea6c2555d78542a9079f4c17aa301a54a29fed5a1d582d0b3bcbed656da46023fb9190bdea428
6
+ metadata.gz: 1b5cfc945a0cbe534a01010b78a263c380943591889839b07a271577a7815ebe9ec03eaed6ac5247cfdbcc3e94ce8f7d9986cb85a8ba7684e45cd0edf3a59cca
7
+ data.tar.gz: fca7aa528b8aff694f213ec0e8aea6744185060556090a2dfe89d3fb5e2bd95639816832b91ead81203fabb01e1187eac237ea0060e38d86f693458e8d9e5475
data/.gitignore CHANGED
@@ -14,3 +14,4 @@ Gemfile.lock
14
14
  *.swo
15
15
 
16
16
  .byebug_history
17
+ strong_versions-*.gem
data/README.md CHANGED
@@ -13,8 +13,8 @@ _StrongVersions_ is a _Bundler_ plugin that enforces a strict policy on your `Ge
13
13
  * The pessimistic `~>` operator must be used for all gem requirement definitions.
14
14
  * If the gem version is greater than 1, the requirement format must be `major.minor`, e.g. `'~> 2.5`'
15
15
  * If the gem version is less than 1, the requirement format must be `major.minor.patch`, e.g. `'~> 0.8.9'`
16
- * An upper bound can be specified as long as a valid pessimistic version is also specified, e.g. `'~> 8.4', '<= 8.4.7'`
17
- * All gems with a `path` source are ignored, e.g. `path: '/path/to/gem'`
16
+ * An upper bound can be specified as long as a valid pessimistic version is also specified, e.g. `'~> 8.4', '< 8.6.7' # Bug introduced in 8.6.7`
17
+ * All gems with a `path` or `git` source are ignored, e.g. `path: '/path/to/gem'`, `git: 'https://github.com/bobf/strong_versions'`
18
18
  * All gems specified in the [ignore list](#ignore) are ignored.
19
19
 
20
20
  Any gems that do not satisfy these rules will cause `bundle install` to fail and give output detailing which gems did not meet the standard and why.
@@ -28,7 +28,7 @@ The benefit of applying this standard is that it [should](https://semver.org/) a
28
28
  Add the plugin to your `Gemfile`
29
29
 
30
30
  ```ruby
31
- plugin 'strong_versions', '~> 0.2.0'
31
+ plugin 'strong_versions', '~> 0.2.1'
32
32
  ```
33
33
 
34
34
  And rebuild your bundle:
@@ -39,7 +39,9 @@ $ bundle install
39
39
 
40
40
  ## Usage
41
41
 
42
- Once the plugin is installed it will automatically hook into _Bundler_ and raise an exception every time you call `bundle install` if there are any errors.
42
+ _StrongVersions_ will automatically hook into _Bundler_ and raise an exception every time you call `bundle install` if there are any errors.
43
+
44
+ If you prefer to see a warning rather than raise an exception, see [raise or warn](#raise_or_warn).
43
45
 
44
46
  ### Exclusions
45
47
 
@@ -53,7 +55,7 @@ ignore:
53
55
 
54
56
  ### Raise or Warn
55
57
 
56
- _StrongVersions_ can be configured to raise an exception (default) or output a warning when the standard is not met.
58
+ <a name="raise_or_warn"></a>_StrongVersions_ can be configured to raise an exception (default) or output a warning when the standard is not met.
57
59
 
58
60
  Warning instead of raising is especially useful when you want to add new dependencies to your `Gemfile` as you can initially set them with loose requirements and then update the `Gemfile` with more precise values based on your new `Gemfile.lock`.
59
61
 
@@ -1,19 +1,33 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'colorize'
4
- require 'i18n'
5
3
  require 'yaml'
6
4
 
7
- I18n.config.available_locales = :en
8
- I18n.load_path += Dir[
9
- File.join(File.expand_path('..', __dir__), 'config', 'locales', '**', '*.yml')
10
- ]
11
-
12
- require 'strong_versions/version'
5
+ begin
6
+ require 'i18n'
7
+ I18n.config.available_locales = :en
8
+ I18n.load_path += Dir[
9
+ File.join(
10
+ File.expand_path('..', __dir__), 'config', 'locales', '**', '*.yml'
11
+ )
12
+ ]
13
+ rescue LoadError
14
+ require 'strong_versions/i18n_stub'
15
+ end
13
16
 
17
+ require 'strong_versions/config'
14
18
  require 'strong_versions/dependency'
15
19
  require 'strong_versions/dependencies'
16
- require 'strong_versions/config'
20
+ require 'strong_versions/gemfile_dsl'
21
+ require 'strong_versions/install_detector'
22
+ require 'strong_versions/terminal'
23
+ require 'strong_versions/version'
17
24
 
18
25
  module StrongVersions
26
+ def self.installed?
27
+ InstallDetector.new.installed?
28
+ end
29
+
30
+ def self.root
31
+ Pathname.new(File.dirname(__dir__))
32
+ end
19
33
  end
@@ -42,25 +42,17 @@ module StrongVersions
42
42
  end
43
43
 
44
44
  def warn_failure
45
- STDERR.puts("\n" + 'StrongVersions expectations not met:'.red + "\n\n")
45
+ terminal = Terminal.new
46
+ terminal.warn("\nStrongVersions expectations not met:\n")
46
47
  @invalid_gems.each do |gem|
47
- STDERR.puts(format_errors(gem.name, gem.errors))
48
+ terminal.output_errors(gem.name, gem.errors)
48
49
  end
49
- STDERR.puts("\n")
50
+ terminal.puts("\n")
50
51
  end
51
52
 
52
53
  def raise_unknown(on_failure)
53
54
  raise Bundler::Error,
54
55
  I18n.t('errors.unknown_on_failure', on_failure: on_failure)
55
56
  end
56
-
57
- def format_errors(name, errors)
58
- message = "#{name}: ".green
59
- message + errors.map do |error|
60
- type = I18n.t("errors.#{error[:type]}").red
61
- value = error[:value].light_red
62
- '"'.red + "#{type} #{value}" + '"'.red
63
- end.join(', '.red)
64
- end
65
57
  end
66
58
  end
@@ -76,6 +76,8 @@ module StrongVersions
76
76
  end
77
77
 
78
78
  def path_source?
79
+ # Bundler::Source::Git inherits from Bundler::Source::Path so git sources
80
+ # will also return `true`.
79
81
  @dependency.source.is_a?(Bundler::Source::Path)
80
82
  end
81
83
 
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ module StrongVersions
4
+ class GemfileDSL
5
+ attr_reader :_strong_versions__installed
6
+
7
+ def initialize
8
+ @_strong_versions__installed = false
9
+ end
10
+
11
+ def plugin(name, *_args)
12
+ @_strong_versions__installed = true if name == 'strong_versions'
13
+ end
14
+
15
+ # If we don't explicitly define this method then RubyGems' Kernel#gem is
16
+ # called instead.
17
+ def gem(*_args); end
18
+
19
+ private
20
+
21
+ # rubocop:disable Style/MethodMissingSuper
22
+ def method_missing(_method, *_args, &_block); end
23
+ # rubocop:enable Style/MethodMissingSuper
24
+
25
+ def respond_to_missing?(_method)
26
+ true
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ class I18n
4
+ def self.t(key)
5
+ key
6
+ end
7
+
8
+ def self._strong_versions__stub; end
9
+ end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ module StrongVersions
4
+ class InstallDetector
5
+ def initialize(gemfiles = nil)
6
+ @gemfiles = gemfiles.nil? ? Bundler.definition.gemfiles : gemfiles
7
+ @dsl = GemfileDSL.new
8
+ end
9
+
10
+ def installed?
11
+ @gemfiles.each do |gemfile|
12
+ # Bundler uses the same strategy to parse Gemfiles.
13
+ @dsl.instance_eval(
14
+ Bundler.read_file(gemfile).dup.untaint, gemfile.to_s, 1
15
+ )
16
+ end
17
+
18
+ @dsl._strong_versions__installed
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,51 @@
1
+ # frozen_string_literal: true
2
+
3
+ module StrongVersions
4
+ class Terminal
5
+ COLOR_CODES = {
6
+ red: 31,
7
+ green: 32,
8
+ light_red: 91
9
+ }.freeze
10
+
11
+ def initialize(file = STDERR)
12
+ @file = file
13
+ check_i18n
14
+ end
15
+
16
+ def warn(string)
17
+ puts(color(:red, string))
18
+ end
19
+
20
+ def output_errors(name, errors)
21
+ puts(format_errors(name, errors))
22
+ end
23
+
24
+ def puts(string)
25
+ @file.puts(string)
26
+ end
27
+
28
+ private
29
+
30
+ def format_errors(name, errors)
31
+ message = color(:green, "#{name}: ")
32
+ message + errors.map do |error|
33
+ type = color(:red, I18n.t("errors.#{error[:type]}"))
34
+ value = color(:light_red, error[:value])
35
+ color(:red, '"') + "#{type} #{value}" + color(:red, '"')
36
+ end.join(color(:red, ', '))
37
+ end
38
+
39
+ def color(name, string)
40
+ code = COLOR_CODES.fetch(name)
41
+ "\033[#{code}m#{string}\033[39m"
42
+ end
43
+
44
+ def check_i18n
45
+ return unless I18n.respond_to?(:_strong_versions__stub)
46
+
47
+ warn("\n`i18n` not installed. Using fallback.")
48
+ warn('Output will improve when your bundle installation completes.')
49
+ end
50
+ end
51
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module StrongVersions
4
- VERSION = '0.2.0'
4
+ VERSION = '0.2.1'
5
5
  end
data/plugins.rb CHANGED
@@ -3,6 +3,16 @@
3
3
  require 'strong_versions'
4
4
 
5
5
  Bundler::Plugin.add_hook('before-install-all') do |dependencies|
6
+ # `StrongVersions.installed?` checks to see if 'strong_versions' is a
7
+ # dependency (i.e. included in the `Gemfile`). The reason for this is that,
8
+ # once a plugin has been installed, removing it from the `Gemfile` does not
9
+ # remove the plugin or its hooks so the hook will still run on every
10
+ # `bundle install`. I think that is not what a user would expect so we check
11
+ # that the plugin is explicitly referenced in the `Gemfile`.
12
+ run_hook(dependencies) if StrongVersions.installed?
13
+ end
14
+
15
+ def run_hook(dependencies)
6
16
  config_path = Bundler.root.join('.strong_versions.yml')
7
17
  config = StrongVersions::Config.new(config_path)
8
18
 
@@ -24,7 +24,10 @@ Gem::Specification.new do |spec|
24
24
  spec.executables = []
25
25
  spec.require_paths = ['lib']
26
26
 
27
- spec.add_dependency 'colorize', '~> 0.8'
27
+ # Rails 4 is locked to I18n ~> 0.7 so, unfortunately, until we are ready to
28
+ # stop supporting Rails 4 we need to support I18n 0.x and 1.x. At some point,
29
+ # I will do a release that is locked to '~> 1.0' and Rails 4 users can use
30
+ # an older version of the gem but we are not quite there yet.
28
31
  spec.add_dependency 'i18n', '>= 0.5.0'
29
32
 
30
33
  spec.add_development_dependency 'bundler', '~> 1.16'
metadata CHANGED
@@ -1,29 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: strong_versions
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.2.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Bob Farrell
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-10-31 00:00:00.000000000 Z
11
+ date: 2018-11-07 00:00:00.000000000 Z
12
12
  dependencies:
13
- - !ruby/object:Gem::Dependency
14
- name: colorize
15
- requirement: !ruby/object:Gem::Requirement
16
- requirements:
17
- - - "~>"
18
- - !ruby/object:Gem::Version
19
- version: '0.8'
20
- type: :runtime
21
- prerelease: false
22
- version_requirements: !ruby/object:Gem::Requirement
23
- requirements:
24
- - - "~>"
25
- - !ruby/object:Gem::Version
26
- version: '0.8'
27
13
  - !ruby/object:Gem::Dependency
28
14
  name: i18n
29
15
  requirement: !ruby/object:Gem::Requirement
@@ -149,6 +135,10 @@ files:
149
135
  - lib/strong_versions/config.rb
150
136
  - lib/strong_versions/dependencies.rb
151
137
  - lib/strong_versions/dependency.rb
138
+ - lib/strong_versions/gemfile_dsl.rb
139
+ - lib/strong_versions/i18n_stub.rb
140
+ - lib/strong_versions/install_detector.rb
141
+ - lib/strong_versions/terminal.rb
152
142
  - lib/strong_versions/version.rb
153
143
  - plugins.rb
154
144
  - strong_versions.gemspec