cliver 0.1.2 → 0.1.3

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