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 +4 -1
- data/README.md +11 -1
- data/cliver.gemspec +3 -2
- data/lib/cliver.rb +2 -2
- data/lib/cliver/assertion.rb +15 -5
- data/lib/cliver/detector.rb +45 -26
- data/lib/cliver/filter.rb +18 -0
- data/lib/cliver/version.rb +1 -1
- data/lib/cliver/which.rb +2 -2
- data/spec/cliver/assertion_spec.rb +16 -2
- data/spec/cliver/detector_spec.rb +3 -3
- data/spec/cliver_spec.rb +1 -1
- metadata +3 -3
- data/lib/cliver/detector/default.rb +0 -52
data/.travis.yml
CHANGED
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
|
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/
|
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('
|
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
|
data/lib/cliver/assertion.rb
CHANGED
@@ -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
|
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
|
-
|
40
|
-
|
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)
|
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}' " +
|
data/lib/cliver/detector.rb
CHANGED
@@ -2,39 +2,36 @@
|
|
2
2
|
require 'shellwords'
|
3
3
|
|
4
4
|
module Cliver
|
5
|
-
#
|
6
|
-
#
|
7
|
-
|
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
|
-
#
|
19
|
-
|
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
|
-
#
|
25
|
-
#
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
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
|
-
|
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
|
data/lib/cliver/version.rb
CHANGED
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
|
-
|
10
|
+
require 'cliver/which/windows'
|
11
11
|
include Cliver::Which::Windows
|
12
12
|
else
|
13
|
-
|
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.
|
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
|
5
|
+
let(:detector) { Cliver::Detector.new(*args) }
|
6
6
|
let(:defaults) do
|
7
7
|
{
|
8
|
-
version_pattern
|
9
|
-
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.
|
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-
|
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/
|
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
|