cliver 0.1.2 → 0.1.3

Sign up to get free protection for your applications and to get access to all the features.
data/.travis.yml CHANGED
@@ -1,6 +1,5 @@
1
1
  ---
2
2
  language: ruby
3
- before_install: "gem install bundler"
4
3
  script: "bundle exec rake spec"
5
4
  rvm:
6
5
  - 2.0.0
@@ -14,3 +13,4 @@ branches:
14
13
  - /^release\/-.*$/
15
14
  - /^support\/-.*$/
16
15
  - /^hotfix\/-.*$/
16
+ - /^feature\/-.*$/
data/cliver.gemspec CHANGED
@@ -17,6 +17,7 @@ Gem::Specification.new do |spec|
17
17
  spec.executables = spec.files.grep(/^bin\//) { |f| File.basename(f) }
18
18
  spec.test_files = spec.files.grep(/^(test|spec|features)\//)
19
19
  spec.require_paths = ['lib']
20
+ spec.has_rdoc = 'yard'
20
21
 
21
22
  spec.add_development_dependency 'bundler', '~> 1.3'
22
23
  spec.add_development_dependency 'rake'
data/lib/cliver.rb CHANGED
@@ -5,9 +5,32 @@ require 'cliver/assertion'
5
5
  require 'cliver/detector'
6
6
  require 'cliver/detector/default'
7
7
 
8
+ # Cliver is tool for making dependency assertions against
9
+ # command-line executables.
8
10
  module Cliver
9
- # See Cliver::Assertion#assert
11
+ # @see Cliver::Assertion
12
+ # @overload (see Cliver::Assertion#initialize)
13
+ # @param (see Cliver::Assertion#initialize)
14
+ # @raise (see Cliver::Assertion#assert!)
15
+ # @return (see Cliver::Assertion#assert!)
10
16
  def self.assert(*args, &block)
11
- Assertion.assert!(*args, &block)
17
+ Assertion.new(*args, &block).assert!
18
+ end
19
+
20
+ extend self
21
+
22
+ # Wraps Cliver::assert and returns truthy/false instead of raising
23
+ # @see Cliver::assert
24
+ # @overload (see Cliver::Assertion#initialize)
25
+ # @param (see Cliver::Assertion#initialize)
26
+ # @return [False,String] either returns false or the reason why the
27
+ # assertion was unmet.
28
+ def dependency_unmet?(*args, &block)
29
+ Cliver.assert(*args, &block)
30
+ false
31
+ rescue Assertion::DependencyNotMet => error
32
+ # Cliver::Assertion::VersionMismatch -> 'Version Mismatch'
33
+ reason = error.class.name.split('::').last.gsub(/(?<!\A)[A-Z]/, ' \\0')
34
+ "#{reason}: #{error.message}"
12
35
  end
13
36
  end
@@ -9,17 +9,14 @@ module Cliver
9
9
 
10
10
  include Which # platform-specific implementation of `which`
11
11
 
12
+ # An exception class raised when assertion is not met
12
13
  DependencyNotMet = Class.new(ArgumentError)
13
- DependencyVersionMismatch = Class.new(DependencyNotMet)
14
- DependencyNotFound = Class.new(DependencyNotMet)
15
14
 
16
- EXECUTABLE_PATTERN = /\A[a-z][a-zA-Z0-9\-_]*\z/.freeze
15
+ # An exception that is raised when executable present is the wrong version
16
+ DependencyVersionMismatch = Class.new(DependencyNotMet)
17
17
 
18
- # Creates a new instance with the args and calls #assert.
19
- # @see #assert
20
- def self.assert!(*args, &block)
21
- new(*args, &block).assert!
22
- end
18
+ # An exception that is raised when executable is not present
19
+ DependencyNotFound = Class.new(DependencyNotMet)
23
20
 
24
21
  # @overload initialize(executable, *requirements, options = {})
25
22
  # @param executable [String]
@@ -29,15 +26,13 @@ module Cliver
29
26
  # Where <operator> is optional (default '='') and in the set
30
27
  # '=', '!=', '>', '<', '>=', '<=', or '~>'
31
28
  # And <version> is dot-separated integers with optional
32
- # alphanumeric pre-release suffix
33
- # @see Gem::Requirement::new
29
+ # alphanumeric pre-release suffix. See also
30
+ # {http://docs.rubygems.org/read/chapter/16 Specifying Versions}
34
31
  # @param options [Hash<Symbol,Object>]
35
- # @options options [Cliver::Detector, #to_proc] :detector
32
+ # @option options [Cliver::Detector, #to_proc] :detector
36
33
  # @yieldparam [String] full path to executable
37
34
  # @yieldreturn [String] Gem::Version-parsable string version
38
35
  def initialize(executable, *args, &detector)
39
- raise ArgumentError, 'executable' unless executable[EXECUTABLE_PATTERN]
40
-
41
36
  options = args.last.kind_of?(Hash) ? args.pop : {}
42
37
 
43
38
  @executable = executable.dup.freeze
@@ -49,14 +44,17 @@ module Cliver
49
44
  # @raise [DependencyNotFound] if no installed version on your path
50
45
  def assert!
51
46
  version = installed_version
52
- raise(DependencyNotFound, "#{@executable} missing.") unless version
47
+ raise(DependencyNotFound, "'#{@executable}' missing.") unless version
53
48
 
54
49
  if @requirement && !@requirement.satisfied_by?(Gem::Version.new(version))
55
50
  raise DependencyVersionMismatch,
56
- "expected #{@executable} to be #{@requirement}, got #{version}"
51
+ "expected '#{@executable}' to be #{@requirement}, got #{version}"
57
52
  end
58
53
  end
59
54
 
55
+ # Finds the executable on your path using {Cliver::Which};
56
+ # if the executable is present and version requirements are specified,
57
+ # uses the specified detector to get the current version.
60
58
  # @private
61
59
  # @return [nil] if no version present
62
60
  # @return [String] Gem::Version-parsable string version
@@ -6,15 +6,19 @@ module Cliver
6
6
  # @see Cliver::Detector::Default for reference implementation
7
7
  module Detector
8
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)
9
14
  def self.new(*args, &block)
10
15
  Default.new(*args, &block)
11
16
  end
12
17
 
13
- # @param executable [String] the executable to test
18
+ # @param executable_path [String] the executable to test
14
19
  # @return [Array<String>]
15
- def version_command(executable)
16
- raise NotImplementedError unless defined? super
17
- super
20
+ def version_command(executable_path)
21
+ raise NotImplementedError
18
22
  end
19
23
 
20
24
  # @return [Regexp] - the pattern used against the output
@@ -25,19 +29,18 @@ module Cliver
25
29
  super
26
30
  end
27
31
 
28
- # @param executable [String] - the path to the executable to test
32
+ # @param executable_path [String] - the path to the executable to test
29
33
  # @return [String] - should be Gem::Version-parsable.
30
- def detect_version(executable)
31
- command_parts = version_command(executable)
32
- escaped_command_parts = command_parts.map(&Shellwords.method(:escape))
33
- output = `#{escaped_command_parts.join(' ')} 2>&1`
34
+ def detect_version(executable_path)
35
+ output = `#{version_command(executable_path).shelljoin} 2>&1`
34
36
  ver = output.scan(version_pattern)
35
37
  ver && ver.first
36
38
  end
37
39
 
38
40
  # This is the interface that any detector must have.
39
- # @see #detect_version for the returned proc's method signature.
40
- # @return [Proc]
41
+ # If not overridden, returns a proc that wraps #detect_version
42
+ # @see #detect_version
43
+ # @return [Proc] following method signature of {#detect_version}
41
44
  def to_proc
42
45
  method(:detect_version).to_proc
43
46
  end
@@ -8,7 +8,11 @@ module Cliver
8
8
  class Detector::Default < Struct.new(:command_arg, :version_pattern)
9
9
  include Detector
10
10
 
11
+ # Default pattern to use when searching {#version_command} output
11
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
12
16
  DEFAULT_COMMAND_ARG = '--version'.freeze
13
17
 
14
18
  # Forgiving input, allows either argument if only one supplied.
@@ -24,16 +28,25 @@ module Cliver
24
28
  super(command_arg, version_pattern)
25
29
  end
26
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)
27
35
  def version_pattern
28
36
  super || DEFAULT_VERSION_PATTERN
29
37
  end
30
38
 
39
+ # The argument to pass to the executable to get current version
40
+ # Defaults to {DEFAULT_COMMAND_ARG}
41
+ # @return [String]
31
42
  def command_arg
32
43
  super || DEFAULT_COMMAND_ARG
33
44
  end
34
45
 
35
- def version_command(executable)
36
- [executable, command_arg]
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]
37
50
  end
38
51
  end
39
52
  end
@@ -1,5 +1,6 @@
1
1
  # encoding: utf-8
2
2
 
3
3
  module Cliver
4
- VERSION = '0.1.2'
4
+ # Cliver follows {http://semver.org SemVer}
5
+ VERSION = '0.1.3'
5
6
  end
@@ -6,6 +6,7 @@ module Cliver
6
6
  # Posix implementation of Which
7
7
  # Required and mixed into Cliver::Which in posix environments
8
8
  module Posix
9
+ # Posix adapter to `which`
9
10
  # @param executable [String]
10
11
  # @return [nil,String] - path to found executable
11
12
  def which(executable)
@@ -6,13 +6,14 @@ module Cliver
6
6
  # Windows-specific implementation of Which
7
7
  # Required and mixed into Cliver::Which in windows environments
8
8
  module Windows
9
+ # Windows-specific implementation of `which`
9
10
  # @param executable [String]
10
11
  # @return [nil,String] - path to found executable
11
12
  def which(executable)
12
13
  # `where` returns newline-separated files found on path, but doesn't
13
14
  # ensure that they are executable as commands.
14
15
  where = `where #{Shellwords.escape executable} 2>&1`
15
- where.split("\n").find do |found|
16
+ where.lines.map(&:chomp).find do |found|
16
17
  next if found.empty?
17
18
  File.executable?(found)
18
19
  end
data/spec/cliver_spec.rb CHANGED
@@ -3,4 +3,29 @@ require 'cliver'
3
3
 
4
4
  describe Cliver do
5
5
  it { should respond_to :assert }
6
+
7
+ it { should respond_to :dependency_unmet? }
8
+ context '#dependency_unmet?' do
9
+ let(:requirements) { [] }
10
+ let(:detector) { proc { } }
11
+ subject { Cliver.dependency_unmet?(executable, *requirements, &detector) }
12
+ context 'when dependency is met' do
13
+ let(:executable) { 'ruby' }
14
+ it { should be_false }
15
+ end
16
+ context 'when dependency is present, but wrong version' do
17
+ let(:executable) { 'ruby' }
18
+ let(:requirements) { ['~>0.1.0'] }
19
+ let(:detector) { proc { RUBY_VERSION.sub('p', '.') } }
20
+ it { should_not be_false }
21
+ it { should match 'Dependency Version Mismatch:' }
22
+ it { should match "expected 'ruby' to be #{requirements}" }
23
+ end
24
+ context 'when dependency is not present' do
25
+ let(:executable) { 'ruxxxby' }
26
+ it { should_not be_false }
27
+ it { should match 'Dependency Not Found:' }
28
+ it { should match "'#{executable}' missing" }
29
+ end
30
+ end
6
31
  end
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.2
4
+ version: 0.1.3
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-19 00:00:00.000000000 Z
12
+ date: 2013-06-20 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: bundler
@@ -163,4 +163,4 @@ test_files:
163
163
  - spec/cliver/assertion_spec.rb
164
164
  - spec/cliver/detector_spec.rb
165
165
  - spec/cliver_spec.rb
166
- has_rdoc:
166
+ has_rdoc: yard