cliver 0.1.3 → 0.1.4

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.
data/.travis.yml CHANGED
@@ -4,8 +4,11 @@ script: "bundle exec rake spec"
4
4
  rvm:
5
5
  - 2.0.0
6
6
  - 1.9.3
7
- - jruby-19mode # JRuby in 1.9 mode
7
+ - jruby-19mode
8
8
  - rbx-19mode
9
+ - 1.8.7
10
+ - jruby-18mode
11
+ - rbx-18mode
9
12
  branches:
10
13
  only:
11
14
  - develop
data/README.md CHANGED
@@ -51,13 +51,23 @@ Cliver.assert('oddball', '~> 10.1.alpha') do |oddball_path|
51
51
  end
52
52
  ```
53
53
 
54
+ And since some programs don't always spit out nice semver-friendly version
55
+ numbers at all, a filter proc can be supplied to clean it up. Note how the
56
+ filter is applied to both your requirements and the executable's output:
57
+
58
+ ```ruby
59
+ Cliver.assert('built-thing', '~> 2013.4r8273',
60
+ filter: proc { |ver| ver.tr('r','.') })
61
+ ```
62
+
54
63
  Since `Cliver` uses `Gem::Requirement` for version comparrisons, it obeys all
55
64
  the same rules including pre-release semantics.
56
65
 
57
66
  ## Supported Platforms
58
67
 
59
68
  The goal is to have full support for all platforms running ruby >= 1.9.2,
60
- including rubinius and jruby implementations. Windows has support
69
+ including rubinius and jruby implementations, as well as basic support for
70
+ legacy ruby 1.8.7. Windows has support in the codebase,
61
71
  but is not available as a build target in [travis_ci][].
62
72
 
63
73
  ## See Also:
data/cliver.gemspec CHANGED
@@ -4,6 +4,7 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
4
  require 'cliver/version'
5
5
 
6
6
  Gem::Specification.new do |spec|
7
+ RUBY_18 = RUBY_VERSION[/\A1\.8\..*/]
7
8
  spec.name = 'cliver'
8
9
  spec.version = Cliver::VERSION
9
10
  spec.authors = ['Ryan Biesemeyer']
@@ -22,7 +23,7 @@ Gem::Specification.new do |spec|
22
23
  spec.add_development_dependency 'bundler', '~> 1.3'
23
24
  spec.add_development_dependency 'rake'
24
25
  spec.add_development_dependency 'rspec'
25
- spec.add_development_dependency 'ruby-appraiser-reek'
26
- spec.add_development_dependency 'ruby-appraiser-rubocop'
26
+ spec.add_development_dependency 'ruby-appraiser-reek' unless RUBY_18
27
+ spec.add_development_dependency 'ruby-appraiser-rubocop' unless RUBY_18
27
28
  spec.add_development_dependency 'yard'
28
29
  end
data/lib/cliver.rb CHANGED
@@ -3,7 +3,7 @@ require 'cliver/version'
3
3
  require 'cliver/which'
4
4
  require 'cliver/assertion'
5
5
  require 'cliver/detector'
6
- require 'cliver/detector/default'
6
+ require 'cliver/filter'
7
7
 
8
8
  # Cliver is tool for making dependency assertions against
9
9
  # command-line executables.
@@ -30,7 +30,7 @@ module Cliver
30
30
  false
31
31
  rescue Assertion::DependencyNotMet => error
32
32
  # Cliver::Assertion::VersionMismatch -> 'Version Mismatch'
33
- reason = error.class.name.split('::').last.gsub(/(?<!\A)[A-Z]/, ' \\0')
33
+ reason = error.class.name.split(':').last.gsub(/([a-z])([A-Z])/, '\\1 \\2')
34
34
  "#{reason}: #{error.message}"
35
35
  end
36
36
  end
@@ -18,6 +18,9 @@ module Cliver
18
18
  # An exception that is raised when executable is not present
19
19
  DependencyNotFound = Class.new(DependencyNotMet)
20
20
 
21
+ # A pattern for extracting a {Gem::Version}-parsable version
22
+ PARSABLE_GEM_VERSION = /[0-9]+(.[0-9]+){0,4}(.[a-zA-Z0-9]+)?/.freeze
23
+
21
24
  # @overload initialize(executable, *requirements, options = {})
22
25
  # @param executable [String]
23
26
  # @param requirements [Array<String>, String] splat of strings
@@ -29,15 +32,20 @@ module Cliver
29
32
  # alphanumeric pre-release suffix. See also
30
33
  # {http://docs.rubygems.org/read/chapter/16 Specifying Versions}
31
34
  # @param options [Hash<Symbol,Object>]
32
- # @option options [Cliver::Detector, #to_proc] :detector
35
+ # @option options [Cliver::Detector, #to_proc] :detector (Detector.new)
36
+ # @option options [#to_proc] :filter ({Cliver::Filter::IDENTITY})
33
37
  # @yieldparam [String] full path to executable
34
- # @yieldreturn [String] Gem::Version-parsable string version
38
+ # @yieldreturn [String] containing a {Gem::Version}-parsable substring
35
39
  def initialize(executable, *args, &detector)
36
40
  options = args.last.kind_of?(Hash) ? args.pop : {}
41
+ @detector = detector || options.fetch(:detector) { Detector.new }
42
+ @filter = options.fetch(:filter, Filter::IDENTITY).extend(Filter)
37
43
 
38
44
  @executable = executable.dup.freeze
39
- @requirement = Gem::Requirement.new(args) unless args.empty?
40
- @detector = detector || options.fetch(:detector) { Detector.new }
45
+
46
+ unless args.empty?
47
+ @requirement = Gem::Requirement.new(@filter.requirements(args))
48
+ end
41
49
  end
42
50
 
43
51
  # @raise [DependencyVersionMismatch] if installed version does not match
@@ -64,7 +72,9 @@ module Cliver
64
72
  return nil unless executable_path
65
73
  return true unless @requirement
66
74
 
67
- @detector.to_proc.call(executable_path).tap do |version|
75
+ version_string = @detector.to_proc.call(executable_path)
76
+ version_string &&= @filter.to_proc.call(version_string)
77
+ (version_string && version_string[PARSABLE_GEM_VERSION]).tap do |version|
68
78
  unless version
69
79
  raise ArgumentError,
70
80
  "found #{@executable} at '#{executable_path}' " +
@@ -2,39 +2,36 @@
2
2
  require 'shellwords'
3
3
 
4
4
  module Cliver
5
- # The interface for Cliver::Detector classes.
6
- # @see Cliver::Detector::Default for reference implementation
7
- module Detector
8
- # Forward to default implementation
9
- # @see Cliver::Detector::Default
10
- # @overload (see Cliver::Detector::Default#initialize)
11
- # @param (see Cliver::Detector::Default#initialize)
12
- # @raise (see Cliver::Detector::Default#initialize)
13
- # @return (see Cliver::Detector::Default#initialize)
14
- def self.new(*args, &block)
15
- Default.new(*args, &block)
16
- end
5
+ # Default implementation of the detector needed by Cliver::Assertion,
6
+ # which will take anything that #respond_to?(:to_proc)
7
+ class Detector < Struct.new(:command_arg, :version_pattern)
17
8
 
18
- # @param executable_path [String] the executable to test
19
- # @return [Array<String>]
20
- def version_command(executable_path)
21
- raise NotImplementedError
22
- end
9
+ # Default pattern to use when searching {#version_command} output
10
+ DEFAULT_VERSION_PATTERN = /version [0-9][.0-9a-z]+/i.freeze
23
11
 
24
- # @return [Regexp] - the pattern used against the output
25
- # of the #version_command, which should
26
- # typically be Gem::Version-parsable.
27
- def version_pattern
28
- raise NotImplementedError unless defined? super
29
- super
12
+ # Default command argument to use against the executable to get
13
+ # version output
14
+ DEFAULT_COMMAND_ARG = '--version'.freeze
15
+
16
+ # Forgiving input, allows either argument if only one supplied.
17
+ #
18
+ # @overload initialize(command_arg)
19
+ # @overload initialize(version_pattern)
20
+ # @overload initialize(command_arg, version_pattern)
21
+ # @param command_arg [String]
22
+ # @param version_pattern [Regexp]
23
+ def initialize(*args)
24
+ command_arg = args.shift if args.first.kind_of?(String)
25
+ version_pattern = args.shift
26
+ super(command_arg, version_pattern)
30
27
  end
31
28
 
32
29
  # @param executable_path [String] - the path to the executable to test
33
- # @return [String] - should be Gem::Version-parsable.
30
+ # @return [String] - should be contain {Gem::Version}-parsable
31
+ # version number.
34
32
  def detect_version(executable_path)
35
33
  output = `#{version_command(executable_path).shelljoin} 2>&1`
36
- ver = output.scan(version_pattern)
37
- ver && ver.first
34
+ output[version_pattern]
38
35
  end
39
36
 
40
37
  # This is the interface that any detector must have.
@@ -44,5 +41,27 @@ module Cliver
44
41
  def to_proc
45
42
  method(:detect_version).to_proc
46
43
  end
44
+
45
+ # The pattern to match the version in {#version_command}'s output.
46
+ # Defaults to {DEFAULT_VERSION_PATTERN}
47
+ # @return [Regexp] - the pattern used against the output
48
+ # of the #version_command, which should
49
+ # contain a {Gem::Version}-parsable substring.
50
+ def version_pattern
51
+ super || DEFAULT_VERSION_PATTERN
52
+ end
53
+
54
+ # The argument to pass to the executable to get current version
55
+ # Defaults to {DEFAULT_COMMAND_ARG}
56
+ # @return [String]
57
+ def command_arg
58
+ super || DEFAULT_COMMAND_ARG
59
+ end
60
+
61
+ # @param executable_path [String] the executable to test
62
+ # @return [Array<String>]
63
+ def version_command(executable_path)
64
+ [executable_path, command_arg]
65
+ end
47
66
  end
48
67
  end
@@ -0,0 +1,18 @@
1
+ # encoding: utf-8
2
+
3
+ module Cliver
4
+ # A Namespace to hold filter procs
5
+ module Filter
6
+ # The identity filter returns its input unchanged.
7
+ IDENTITY = proc { |version| version }
8
+
9
+ def requirements(requirements)
10
+ requirements.map do |requirement|
11
+ req_parts = requirement.split(/\b(?=\d)/, 2)
12
+ version = req_parts.last
13
+ version.replace call(version)
14
+ req_parts.join
15
+ end
16
+ end
17
+ end
18
+ end
@@ -2,5 +2,5 @@
2
2
 
3
3
  module Cliver
4
4
  # Cliver follows {http://semver.org SemVer}
5
- VERSION = '0.1.3'
5
+ VERSION = '0.1.4'
6
6
  end
data/lib/cliver/which.rb CHANGED
@@ -7,10 +7,10 @@ module Cliver
7
7
  module Which
8
8
  case RbConfig::CONFIG['host_os']
9
9
  when /mswin|msys|mingw|cygwin|bccwin|wince|emc/
10
- require_relative 'which/windows'
10
+ require 'cliver/which/windows'
11
11
  include Cliver::Which::Windows
12
12
  else
13
- require_relative 'which/posix'
13
+ require 'cliver/which/posix'
14
14
  include Cliver::Which::Posix
15
15
  end
16
16
  end
@@ -96,9 +96,23 @@ describe Cliver::Assertion do
96
96
  end
97
97
  end
98
98
  let(:detector_touches) { [] }
99
+ context 'ruby using filter' do
100
+ let(:requirement) { '~> 1.2.3p112' }
101
+ let(:executable) { 'ruby' }
102
+ let(:filter) { proc { |ver| ver.tr('p', '.') } }
103
+ let(:detector) { proc { '1.2.3p456' } }
104
+ let(:assertion) do
105
+ Cliver::Assertion.new(executable, requirement, :filter => filter,
106
+ :detector => detector)
107
+ end
108
+ let(:installed_version) { assertion.installed_version }
109
+ subject { installed_version }
110
+
111
+ it { should eq '1.2.3.456' }
112
+ end
99
113
  context 'ruby with detector-block returned value' do
100
114
  let(:requirements) { ['~> 10.1.4'] }
101
- let(:fake_version) { '10.1.5' }
115
+ let(:fake_version) { 'ruby 10.1.5' }
102
116
  let(:executable) { 'ruby' }
103
117
  let(:detector) do
104
118
  proc do |ruby|
@@ -116,7 +130,7 @@ describe Cliver::Assertion do
116
130
  end
117
131
  end
118
132
  context 'when block-return doesn\'t meet requirements' do
119
- let(:fake_version) { '10.1.3' }
133
+ let(:fake_version) { '10.1433.32.alpha' }
120
134
  it 'should raise' do
121
135
  expect { assertion.assert! }.to raise_exception mismatch_exception
122
136
  end
@@ -2,11 +2,11 @@
2
2
  require 'cliver'
3
3
 
4
4
  describe Cliver::Detector do
5
- let(:detector) { Cliver::Detector::Default.new(*args) }
5
+ let(:detector) { Cliver::Detector.new(*args) }
6
6
  let(:defaults) do
7
7
  {
8
- version_pattern: Cliver::Detector::Default::DEFAULT_VERSION_PATTERN,
9
- command_arg: Cliver::Detector::Default::DEFAULT_COMMAND_ARG,
8
+ :version_pattern => Cliver::Detector::DEFAULT_VERSION_PATTERN,
9
+ :command_arg => Cliver::Detector::DEFAULT_COMMAND_ARG,
10
10
  }
11
11
  end
12
12
  let(:args) { [] }
data/spec/cliver_spec.rb CHANGED
@@ -15,7 +15,7 @@ describe Cliver do
15
15
  end
16
16
  context 'when dependency is present, but wrong version' do
17
17
  let(:executable) { 'ruby' }
18
- let(:requirements) { ['~>0.1.0'] }
18
+ let(:requirements) { ['~> 0.1.0'] }
19
19
  let(:detector) { proc { RUBY_VERSION.sub('p', '.') } }
20
20
  it { should_not be_false }
21
21
  it { should match 'Dependency Version Mismatch:' }
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cliver
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.3
4
+ version: 0.1.4
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-06-20 00:00:00.000000000 Z
12
+ date: 2013-06-22 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: bundler
@@ -126,7 +126,7 @@ files:
126
126
  - lib/cliver.rb
127
127
  - lib/cliver/assertion.rb
128
128
  - lib/cliver/detector.rb
129
- - lib/cliver/detector/default.rb
129
+ - lib/cliver/filter.rb
130
130
  - lib/cliver/version.rb
131
131
  - lib/cliver/which.rb
132
132
  - lib/cliver/which/posix.rb
@@ -1,52 +0,0 @@
1
- # encoding: utf-8
2
- require 'open3'
3
-
4
- module Cliver
5
- # Default implementation of Cliver::Detector
6
- # Requires a command argument (default '--version')
7
- # and a pattern-matcher Regexp with sensible default.
8
- class Detector::Default < Struct.new(:command_arg, :version_pattern)
9
- include Detector
10
-
11
- # Default pattern to use when searching {#version_command} output
12
- DEFAULT_VERSION_PATTERN = /(?<=version )[0-9][.0-9a-z]+/i.freeze
13
-
14
- # Default command argument to use against the executable to get
15
- # version output
16
- DEFAULT_COMMAND_ARG = '--version'.freeze
17
-
18
- # Forgiving input, allows either argument if only one supplied.
19
- #
20
- # @overload initialize(command_arg)
21
- # @overload initialize(version_pattern)
22
- # @overload initialize(command_arg, version_pattern)
23
- # @param command_arg [String] ('--version')
24
- # @param version_pattern [Regexp] (/(?<=version )[0-9][.0-9a-z]+/i)
25
- def initialize(*args)
26
- command_arg = args.shift if args.first.kind_of?(String)
27
- version_pattern = args.shift
28
- super(command_arg, version_pattern)
29
- end
30
-
31
- # The pattern to match the version in {#version_command}'s output.
32
- # Defaults to {DEFAULT_VERSION_PATTERN}
33
- # @overload (see Cliver::Detector#version_pattern)
34
- # @return (see Cliver::Detector#version_pattern)
35
- def version_pattern
36
- super || DEFAULT_VERSION_PATTERN
37
- end
38
-
39
- # The argument to pass to the executable to get current version
40
- # Defaults to {DEFAULT_COMMAND_ARG}
41
- # @return [String]
42
- def command_arg
43
- super || DEFAULT_COMMAND_ARG
44
- end
45
-
46
- # @overload (see Cliver::Detector#version_command)
47
- # @return (see Cliver::Detector#version_command)
48
- def version_command(executable_path)
49
- [executable_path, command_arg]
50
- end
51
- end
52
- end