cliver 0.1.3 → 0.1.4

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