strong_versions 0.2.0 → 0.2.1

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
  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