bindep 0.0.1

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.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ !binary "U0hBMQ==":
3
+ metadata.gz: 158a70fba74e7159c2f9f1a2fec4ffacb7ce5ae9
4
+ data.tar.gz: 4742cd55e48e01349f82fe97f2ac570b04b94bbb
5
+ SHA512:
6
+ metadata.gz: 6427680d083cf0373284f787e936120b8a6a4ed2d4525201f632434215258236dc197f1de43950f1c8ade05b834adcba7455c0b6e0c98e7cee2d9599d3d9462f
7
+ data.tar.gz: d5364eb79015a159342798713c3f723e2559f3eadfba392cbf326ad443ad2615d8356072a8edba6af15a23b3f2b15657f337f3308381efb4d961aa08c86a948f
data/.gitignore ADDED
@@ -0,0 +1,8 @@
1
+ *.gem
2
+ .bundle
3
+ Bindepfile
4
+ Gemfile.lock
5
+ coverage
6
+ test.rb
7
+ .DS_Store
8
+ tmp
data/.travis.yml ADDED
@@ -0,0 +1,10 @@
1
+ ---
2
+ language: ruby
3
+
4
+ rvm:
5
+ - 1.9.3
6
+ - 2.0.0
7
+ - 2.1.0
8
+ - ruby-head
9
+
10
+ script: bundle exec rspec
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "https://rubygems.org"
2
+
3
+ # Specify your gem"s dependencies in bindep.gemspec
4
+ gemspec
data/Guardfile ADDED
@@ -0,0 +1,3 @@
1
+ guard :rspec, cmd: "bundle exec rspec --color" do
2
+ watch(%r{(.+)\.rb$}){ "spec" }
3
+ end
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 Niko Dziemba, niko@dziemba.com
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,139 @@
1
+ # Bindep
2
+
3
+ A simple way to manage binary dependencies for multiple platforms.
4
+
5
+ [![Build Status](https://travis-ci.org/dziemba/bindep.svg?branch=master)](https://travis-ci.org/dziemba/bindep) [![Code Climate](https://codeclimate.com/github/dziemba/bindep.png)](https://codeclimate.com/github/dziemba/bindep)
6
+
7
+ ## Example
8
+
9
+ To install git and complile some less code:
10
+ ``` ruby
11
+
12
+ require 'bindep'
13
+ require 'bindep/library'
14
+
15
+ # prompt user to install git if it is not available, do nothing otherwise
16
+ Bindep.check 'git'
17
+
18
+ # prompt to install less compiler if it is not available,
19
+ # then run it with given parameters
20
+ css_code, stderr = Bindep.run :less, '-x -', less_code
21
+ ```
22
+
23
+ ## Installation
24
+
25
+ Install the gem:
26
+
27
+ ``` shell
28
+ gem install bindep
29
+ ```
30
+
31
+ ## Usage
32
+
33
+ Load the gem:
34
+ ``` ruby
35
+ require "bindep" # core module
36
+ require "bindep/library" # predefined packages (optional)
37
+ ```
38
+
39
+ Check if a package is available and prompt the user to install it otherwise:
40
+ ``` ruby
41
+ Bindep.check 'git'
42
+ ```
43
+
44
+ Run commands (`run` calls `check` automatically):
45
+ ``` ruby
46
+ # syntax
47
+ stdout, stderr, exitcode = Bindep.run :package, stdin, raise_on_error
48
+
49
+ # no exception on failure
50
+ css_code, stderr, exitcode = Bindep.run :less, '-x -', less_code, false
51
+ css_code = '' unless exitcode.zero?
52
+
53
+ # raise on failure
54
+ begin
55
+ output, stderr = Bindep.run :git, 'status'
56
+ puts output
57
+ rescue RuntimeError
58
+ puts 'Git failed!'
59
+ end
60
+
61
+ ```
62
+
63
+ Define new packages and check/install them:
64
+ ``` ruby
65
+ Bindep.define(:npm) do |i|
66
+ i.command = "npm"
67
+ i.apt = [ "nodejs", "npm" ]
68
+ i.brew = "node"
69
+ end
70
+
71
+ Bindep.define(:lessc) do |i|
72
+ i.command = "lessc"
73
+ i.npm = "lessc"
74
+ i.depends = [ :npm ]
75
+ end
76
+
77
+ Bindep.check :lessc
78
+ ```
79
+
80
+ Combine `define` and `check`:
81
+ ``` ruby
82
+
83
+ Bindep.check(:git) do |i|
84
+ i.command = "npm"
85
+ i.apt = "git-core"
86
+ i.brew = "git"
87
+ i.yum = "git-core"
88
+ end
89
+ ```
90
+
91
+ ## Command Line Usage
92
+
93
+ Create a `Bindepfile` in your project root using the same syntax:
94
+ ``` ruby
95
+ check 'less'
96
+
97
+ check(:git) do |i|
98
+ i.command = "npm"
99
+ i.apt = "git-core"
100
+ i.brew = "git"
101
+ i.yum = "git-core"
102
+ end
103
+ ```
104
+
105
+ and execute it by running `bindep` in your shell.
106
+
107
+
108
+ ## Configuration
109
+ Add any of the following lines to your code before running any bindep commands.
110
+
111
+ ``` ruby
112
+ # Abort if command is not found, do not try to install.
113
+ Bindep.no_install = true
114
+
115
+ # Do not ask user for confirmation before installing.
116
+ Bindep.no_confirm_before_install = true
117
+
118
+ # Do not output error messages and exit process but raise exceptions instead.
119
+ Bindep.silent_exceptions = true
120
+ ```
121
+
122
+ You can also set these in your `Bindepfile` by adding any of the following before the commands:
123
+ ``` ruby
124
+ @no_install = true
125
+ @no_confirm_before_install = true
126
+ @silent_exceptions = true
127
+ ```
128
+
129
+ ## Contributing
130
+
131
+ I really appreciate any input, either code or new library entries, so please:
132
+
133
+ 1. Fork it ( https://github.com/dziemba/bindep/fork )
134
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
135
+ 3. Commit your changes (`git commit -am "Add some feature"`)
136
+ 4. Push to the branch (`git push origin my-new-feature`)
137
+ 5. Create a new Pull Request
138
+
139
+
data/bin/bindep ADDED
@@ -0,0 +1,11 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'bindep'
4
+ require 'bindep/library'
5
+
6
+ if $1 == "--help"
7
+ puts "Usage: $0 [Bindepfile]"
8
+ exit 0
9
+ end
10
+
11
+ Bindep.load_file($1 || 'Bindepfile')
data/bindep.gemspec ADDED
@@ -0,0 +1,26 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path("../lib", __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require "bindep/version"
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "bindep"
8
+ spec.version = Bindep::VERSION
9
+ spec.authors = ["Niko Dziemba"]
10
+ spec.email = ["niko@dziemba.com"]
11
+ spec.summary = "A simple way to manage binary dependencies for multiple platforms."
12
+ spec.description = spec.summary
13
+ spec.homepage = "https://github.com/dziemba/bindep"
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files -z`.split("\x0")
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_development_dependency "bundler"
22
+ spec.add_development_dependency "rake"
23
+ spec.add_development_dependency "rspec"
24
+ spec.add_development_dependency "guard-rspec"
25
+ spec.add_development_dependency "simplecov"
26
+ end
data/lib/bindep.rb ADDED
@@ -0,0 +1,10 @@
1
+ require "open3"
2
+
3
+ require "bindep/version"
4
+ require "bindep/error"
5
+ require "bindep/helpers"
6
+ require "bindep/os"
7
+ require "bindep/core"
8
+ require "bindep/item"
9
+ require "bindep/context"
10
+
@@ -0,0 +1,91 @@
1
+ module Bindep
2
+ class Context
3
+ attr_accessor :no_install, :no_confirm_before_install, :silent_exceptions
4
+
5
+ # Create a new Bindep context with its own options and item registry.
6
+ def initialize
7
+ @registry = {}
8
+
9
+ @no_install = false
10
+ @no_confirm_before_install = false
11
+ @silent_exceptions = false
12
+
13
+ unless Helpers.which_test
14
+ error "Command detection does not work on your system. Bindep cannot run on your system!"
15
+ end
16
+ end
17
+
18
+ # Define a new item.
19
+ def define(id, &block)
20
+ item = Item.new(id)
21
+ yield item
22
+
23
+ @registry[item.id] = item
24
+ end
25
+
26
+ # Check if a given item is installed, can also define item beforehand if block is given.
27
+ def check(id, force_install = false, &block)
28
+ item = block_given? ? define(id, &block) : get_item(id)
29
+
30
+ [ item.depends ].flatten.compact.each { |dep| check dep }
31
+
32
+ install item if force_install || (item.local_command.nil? && !no_install)
33
+ end
34
+
35
+ # Runs the specified command with the given arguments.
36
+ def run(id, args = [], stdin = nil, raise_on_failure = true)
37
+ check id
38
+
39
+ cmd_string = "#{get_item(id).local_command} #{[ args ].flatten.join(" ")}".strip
40
+ Helpers.cmd cmd_string, stdin, raise_on_failure
41
+ end
42
+
43
+ # Gets an item from the registry.
44
+ def get_item(id)
45
+ @registry[id.to_sym] || raise(Error, "Cannot find item '#{id.to_sym}' in context!")
46
+ end
47
+
48
+ private
49
+ def pre_install(item)
50
+ if no_install
51
+ error "Cannot find command for '#{item.id}' and installation is deactivated. "\
52
+ "Please install manually."
53
+ end
54
+
55
+ if item.install_command.nil?
56
+ error "Cannot find installation instructions for '#{item.id}'. "\
57
+ "Please install manually."
58
+ end
59
+
60
+ unless no_confirm_before_install
61
+ puts "[Bindep] Command '#{item.id}' is not installed. "\
62
+ "Do you want to run the following command? (y/n)"
63
+ end
64
+
65
+ puts "[Bindep] $ #{item.install_command}\n"
66
+
67
+ unless no_confirm_before_install
68
+ error "Aborting." unless gets.downcase.strip == 'y'
69
+ end
70
+ end
71
+
72
+ def install(item)
73
+ pre_install item
74
+
75
+ Helpers.cmd_interactive item.install_command
76
+
77
+ unless item.local_command true
78
+ error "Installation for '#{item.id}' failed. Please install manually."
79
+ end
80
+ end
81
+
82
+ def error(message = nil)
83
+ exception = Error.new message
84
+
85
+ raise exception if silent_exceptions
86
+
87
+ puts exception.to_s
88
+ exit 1
89
+ end
90
+ end
91
+ end
@@ -0,0 +1,16 @@
1
+ module Bindep
2
+ # Get the global context instance, create a new one on first call.
3
+ def self.context
4
+ @context ||= Context.new
5
+ end
6
+
7
+ # Evaluate a Bindepfile in the global context.
8
+ def self.load_file(filename = 'Bindepfile')
9
+ context.instance_eval File.read(filename)
10
+ end
11
+
12
+ # Redirect all other method calls to the global context instance.
13
+ def self.method_missing(method, *args, &block)
14
+ context.send method, *args, &block
15
+ end
16
+ end
@@ -0,0 +1,7 @@
1
+ module Bindep
2
+ class Error < RuntimeError
3
+ def to_s
4
+ "[Bindep] #{super.to_s}"
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,36 @@
1
+ module Bindep
2
+ module Helpers
3
+ # Run a command, supply stdin and capture stdout and stderr.
4
+ def self.cmd(command, stdin = nil, raise_on_error = true)
5
+ stdout, stderr, status = Open3.capture3 command, stdin_data: stdin, binmode: true
6
+
7
+ if raise_on_error && (status.exitstatus != 0 || stderr =~ /error/i)
8
+ raise RuntimeError, "Command '#{command}' returned status #{status.exitstatus}"
9
+ end
10
+
11
+ [ stdout, stderr, status.exitstatus ]
12
+ end
13
+
14
+ # Run a command interactively, return exit status
15
+ def self.cmd_interactive(command, raise_on_error = true)
16
+ system command
17
+
18
+ if raise_on_error && !$?.exitstatus.zero?
19
+ raise RuntimeError, "Command '#{command}' returned status #{$?.exitstatus}"
20
+ end
21
+
22
+ $?.exitstatus
23
+ end
24
+
25
+ # Check if a shell command exists (using "which").
26
+ def self.command_exists?(cmd)
27
+ _, _, status = Helpers.cmd "which #{cmd.strip}", nil, false
28
+ status.zero?
29
+ end
30
+
31
+ # Check if "which" command is available and works correctly.
32
+ def self.which_test
33
+ command_exists?("which") && !command_exists?("foo_bar_command_does_not_exist")
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,35 @@
1
+ module Bindep
2
+ class Item
3
+ attr_reader :id
4
+ attr_accessor :command, :apt, :yum, :brew, :npm, :rubygem, :install_command, :depends
5
+
6
+ def initialize(id)
7
+ @id = id.to_sym
8
+ end
9
+
10
+ # Get the command for the current system. Return nil if command is not available.
11
+ def local_command(reset = false)
12
+ @local_command = nil if reset
13
+
14
+ @local_command ||= [ command ].flatten.compact.find do |cmd|
15
+ Helpers.command_exists? cmd
16
+ end
17
+ end
18
+
19
+ # Get the installation commands for the current system as a single string.
20
+ # Return nil if there is no command that fits the current system.
21
+ def install_command
22
+ list = []
23
+
24
+ list << OS.apt_install(apt) if apt && OS.apt?
25
+ list << OS.yum_install(yum) if yum && OS.yum?
26
+ list << OS.brew_install(brew) if brew && OS.brew?
27
+ list << OS.npm_install(npm) if npm && OS.npm?
28
+ list << OS.rubygem_install(rubygem) if rubygem && OS.rubygem?
29
+ list << @install_command if @install_command
30
+
31
+ list.empty? ? nil : list.join("; ")
32
+ end
33
+ end
34
+ end
35
+
@@ -0,0 +1,53 @@
1
+ module Bindep
2
+
3
+ # Example, for testing.
4
+ define(:does_not_exist) do |i|
5
+ i.command = 'does_not_exist'
6
+ # i.install_command = 'echo "This should install the command"'
7
+ end
8
+
9
+ define(:nmap) do |i|
10
+ i.command = 'nmap'
11
+ i.apt = 'nmap'
12
+ i.yum = 'nmap'
13
+ i.brew = 'nmap'
14
+ end
15
+
16
+ define(:git) do |i|
17
+ i.command = 'git'
18
+ i.apt = 'git-core'
19
+ i.yum = 'git-core'
20
+ i.brew = 'git'
21
+ end
22
+
23
+ define(:nodejs) do |i|
24
+ i.command = %w(nodejs node)
25
+ i.apt = %w(nodejs npm)
26
+ i.yum = %w(nodejs npm)
27
+ i.brew = 'node'
28
+ end
29
+
30
+ define(:npm) do |i|
31
+ i.command = 'npm'
32
+ i.depends = 'nodejs'
33
+ end
34
+
35
+ define(:less) do |i|
36
+ i.command = 'lessc'
37
+ i.npm = 'less'
38
+ i.depends = 'npm'
39
+ end
40
+
41
+ define(:uglifyjs) do |i|
42
+ i.command = 'uglifyjs'
43
+ i.npm = 'uglify-js'
44
+ i.depends = 'npm'
45
+ end
46
+
47
+ define(:jshint) do |i|
48
+ i.command = 'jshint'
49
+ i.npm = 'jshint'
50
+ i.depends = 'npm'
51
+ end
52
+
53
+ end
data/lib/bindep/os.rb ADDED
@@ -0,0 +1,35 @@
1
+ module Bindep
2
+ module OS
3
+ LIST = {
4
+ :brew => "brew install",
5
+ :apt => "apt-get install -y",
6
+ :yum => "yum install -y",
7
+ :npm => "npm install -g",
8
+ :rubygem => "gem install",
9
+ }
10
+ @command_exists_cache = {}
11
+
12
+ class << self
13
+ LIST.each_pair do |method, install_cmd|
14
+ check_cmd = install_cmd.split(" ").first
15
+
16
+ # Create a "handler?" method which checks if the specified package handler is available.
17
+ define_method("#{method}?") do
18
+ return @command_exists_cache[method] unless @command_exists_cache[method].nil?
19
+ @command_exists_cache[method] = Helpers.command_exists? check_cmd
20
+ end
21
+
22
+ # Create a "handler_install" method which returns the install string for the given handler.
23
+ define_method("#{method}_install") do |package|
24
+ "#{sudo} #{install_cmd} #{package}".strip
25
+ end
26
+ end
27
+ end
28
+
29
+ private
30
+ def self.sudo
31
+ # homebrew does not need sudo for itself and other package managers
32
+ brew? ? "" : "sudo"
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,3 @@
1
+ module Bindep
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,195 @@
1
+ require "spec_helper"
2
+
3
+ describe Bindep::Context do
4
+ let (:context) { Bindep::Context.new }
5
+ let (:item) { context.define(:testitem) { } }
6
+
7
+ it "fails on init if which tests fails" do
8
+ expect(Bindep::Helpers).to receive(:which_test).once.and_return(false)
9
+
10
+ expect_any_instance_of(Bindep::Context).to receive(:error)
11
+ Bindep::Context.new
12
+ end
13
+
14
+ it "fails on getting invalid item" do
15
+ expect do
16
+ context.get_item(:invalid)
17
+ end.to raise_error Bindep::Error, "[Bindep] Cannot find item 'invalid' in context!"
18
+ end
19
+
20
+ it "can define and get a new item" do
21
+ item = context.define(:testid) do |i|
22
+ i.command = "cmd"
23
+ end
24
+
25
+ expect(item).to be_a Bindep::Item
26
+ expect(item.id).to eq :testid
27
+ expect(item.command).to eq "cmd"
28
+
29
+ expect(context.get_item(:testid)).to eq item
30
+ end
31
+
32
+ context "checking" do
33
+ it "fails for an non-existing item and no block" do
34
+ expect do
35
+ context.check :testid
36
+ end.to raise_error Bindep::Error
37
+ end
38
+
39
+ it "work for an non-existing item and a defining block" do
40
+ expect(context).to receive(:install).once
41
+
42
+ context.check(:testid) do |i|
43
+ i.command = "testcmd"
44
+ end
45
+
46
+ expect(context.get_item(:testid).command).to eq "testcmd"
47
+ end
48
+
49
+ it "works for an existing installed item" do
50
+ context.define(:testid) { |i| i.command = "grep" }
51
+
52
+ context.check :testid
53
+ end
54
+
55
+ [ false, true ].each do |no_install|
56
+ context "with no_install #{no_install}" do
57
+ before :each do
58
+ context.no_install = no_install
59
+ end
60
+
61
+ it "works for an existing installed item with force install" do
62
+ item = context.define(:testid) { |i| i.command = "grep" }
63
+
64
+ expect(context).to receive(:install).with(item).once
65
+ context.check :testid, true
66
+ end
67
+
68
+ it "works for an existing but not installed item" do
69
+ item = context.define(:testid) { |i| i.command = "foo_bar_not_existing" }
70
+
71
+ expect(context).to receive(:install).with(item).exactly(no_install ? 0:1).times
72
+ context.check :testid
73
+ end
74
+ end
75
+ end
76
+
77
+ it "works with dependencies" do
78
+ dep1 = context.define(:dep1) {}
79
+ dep2 = context.define(:dep2) {}
80
+ dep3 = context.define(:dep3) { |i| i.depends = "dep2" }
81
+ item = context.define(:item) { |i| i.depends = [ "dep3", "dep1" ] }
82
+
83
+ [ dep2, dep3, dep1, item ].each do |i|
84
+ expect(context).to receive(:install).with(i).once
85
+ end
86
+
87
+ context.check :item
88
+ end
89
+ end
90
+
91
+ context "pre_install" do
92
+ it "aborts if no_install is set" do
93
+ context.no_install = true
94
+
95
+ expect(context).to receive(:error).with(/deactivated/).and_raise(Bindep::Error)
96
+
97
+ expect do
98
+ context.send :pre_install, item
99
+ end.to raise_error Bindep::Error
100
+ end
101
+
102
+ it "aborts if no install command is found" do
103
+ str = /Cannot find installation instructions/
104
+ expect(context).to receive(:error).with(str).and_raise(Bindep::Error)
105
+
106
+ expect do
107
+ context.send :pre_install, item
108
+ end.to raise_error Bindep::Error
109
+ end
110
+
111
+ it "outputs command and does nothing else if no_confirm_before_install is set" do
112
+ context.no_confirm_before_install = true
113
+
114
+ item.install_command = "my_install -b"
115
+
116
+ expect(context).to receive(:puts).with("[Bindep] $ my_install -b\n")
117
+
118
+ context.send :pre_install, item
119
+ end
120
+
121
+ it "asks for confirmation" do
122
+ item.install_command = "my_install -b"
123
+
124
+ expect(context).to receive(:puts).with(/'testitem' is not installed/)
125
+ expect(context).to receive(:puts).with("[Bindep] $ my_install -b\n")
126
+ expect(context).to receive(:gets).once.and_return("y\n")
127
+
128
+ context.send :pre_install, item
129
+ end
130
+
131
+ it "asks for confirmation and aborts if user wants" do
132
+ item.install_command = "my_install -b"
133
+
134
+ expect(context).to receive(:puts).twice
135
+ expect(context).to receive(:gets).once.and_return("bla\n")
136
+ expect(context).to receive(:error).with(/Aborting/)
137
+
138
+ context.send :pre_install, item
139
+ end
140
+ end
141
+
142
+ context "install" do
143
+ it "runs installation command (success)" do
144
+ item.install_command = "echo 1"
145
+ item.command = "cat"
146
+
147
+ expect(context).to receive(:pre_install).with(item)
148
+ expect(Bindep::Helpers).to receive(:system).with("echo 1")
149
+
150
+ context.send :install, item
151
+ end
152
+
153
+ it "runs installation command (fail)" do
154
+ item.install_command = "echo 1"
155
+
156
+ expect(context).to receive(:pre_install).with(item)
157
+ expect(Bindep::Helpers).to receive(:system).with("echo 1")
158
+ expect(context).to receive(:error).with(/Installation for 'testitem' failed/)
159
+
160
+ context.send :install, item
161
+ end
162
+ end
163
+
164
+ it "runs a command" do
165
+ item.command = "mycmd"
166
+
167
+ expect(item).to receive(:local_command).at_least(:once).and_return("mycmd")
168
+ expect(Bindep::Helpers).to receive(:cmd).with("mycmd --myparam mydoc", 'stdin', false)
169
+ expect(Bindep::Helpers).to receive(:cmd).with("mycmd", nil, true)
170
+ expect(Bindep::Helpers).to receive(:cmd).with("mycmd --myparam mydoc", nil, false)
171
+
172
+ context.run :testitem, [ "--myparam", "mydoc" ], 'stdin', false
173
+ context.run :testitem, "", nil, true
174
+ context.run :testitem, "--myparam mydoc", nil, false
175
+ end
176
+
177
+ context "error handler" do
178
+ it 'prints exception and exits' do
179
+ expect(context).to receive(:puts).with("[Bindep] My message").once
180
+
181
+ expect do
182
+ context.send :error, "My message"
183
+ end.to raise_error SystemExit
184
+ end
185
+
186
+ it 'prints raises exception if silent_exceptions is true' do
187
+ context.silent_exceptions = true
188
+
189
+ expect do
190
+ context.send :error, "My message"
191
+ end.to raise_error Bindep::Error, "[Bindep] My message"
192
+ end
193
+ end
194
+ end
195
+
@@ -0,0 +1,36 @@
1
+ require "spec_helper"
2
+
3
+ describe Bindep do
4
+ it "exposes a singleton context instance" do
5
+ context = Bindep.context
6
+
7
+ expect(context).to be_a Bindep::Context
8
+ expect(Bindep.context).to eq context
9
+ end
10
+
11
+ it "evaluates a Bindepfile" do
12
+ file = Tempfile.new('Bindep')
13
+ file.write "check 'test1'\ncheck 'test2'"
14
+ file.close
15
+
16
+ context = Bindep.context
17
+
18
+ expect(context).to receive(:check).with("test1")
19
+ expect(context).to receive(:check).with("test2")
20
+
21
+ Bindep.load_file file.path
22
+
23
+ file.unlink
24
+ end
25
+
26
+ it "sends all method calls to the singleton context instance" do
27
+ context = Bindep.context
28
+
29
+ expect(context).to receive(:define) do |arg, &blk|
30
+ expect(blk.call).to eq :blocktest
31
+ expect(arg).to eq :test1
32
+ end
33
+
34
+ Bindep.define(:test1) { :blocktest }
35
+ end
36
+ end
@@ -0,0 +1,50 @@
1
+ require 'spec_helper'
2
+
3
+ describe Bindep::Helpers do
4
+ context '.cmd_interactive' do
5
+ it 'works on success' do
6
+ expect(Bindep::Helpers.cmd_interactive 'true').to eq 0
7
+ end
8
+
9
+ it 'works on failure' do
10
+ expect(Bindep::Helpers.cmd_interactive 'false', false).to eq 1
11
+ end
12
+
13
+ it 'raises on failure' do
14
+ expect do
15
+ Bindep::Helpers.cmd_interactive 'false'
16
+ end.to raise_error RuntimeError, "Command 'false' returned status 1"
17
+ end
18
+ end
19
+
20
+ context '.cmd' do
21
+ it 'works on success' do
22
+ stdout, stderr, status = Bindep::Helpers.cmd 'cat', 'test'
23
+
24
+ expect(stdout).to eq 'test'
25
+ expect(stderr).to eq ''
26
+ expect(status).to eq 0
27
+ end
28
+
29
+ it 'works on failure' do
30
+ stdout, stderr, status = Bindep::Helpers.cmd 'false', nil, false
31
+ expect(status).to eq 1
32
+ end
33
+
34
+ it 'fails on failure' do
35
+ expect do
36
+ Bindep::Helpers.cmd 'false'
37
+ end.to raise_error RuntimeError, "Command 'false' returned status 1"
38
+ end
39
+ end
40
+
41
+ it 'has .command_exists?' do
42
+ expect(Bindep::Helpers.command_exists? 'cat').to eq true
43
+ expect(Bindep::Helpers.command_exists? 'does_not_exists').to eq false
44
+ end
45
+
46
+ it 'has working which_test' do
47
+ expect(Bindep::Helpers.which_test).to eq true
48
+ end
49
+ end
50
+
@@ -0,0 +1,151 @@
1
+ require "spec_helper"
2
+
3
+ describe Bindep::Item do
4
+ let (:item) { Bindep::Item.new :testid }
5
+
6
+ it "can create a valid item and has read and writable properties" do
7
+ item.command = "command"
8
+ item.apt = "apt"
9
+ item.brew = "brew"
10
+ item.depends = [ :dep1, :dep2 ]
11
+
12
+ expect(item.id).to eq :testid
13
+ expect(item.command).to eq "command"
14
+ expect(item.apt).to eq "apt"
15
+ expect(item.brew).to eq "brew"
16
+ expect(item.depends).to eq [ :dep1, :dep2 ]
17
+ end
18
+
19
+ it "can converts it to symbol" do
20
+ item = Bindep::Item.new "testid"
21
+
22
+ expect(item.id).to eq :testid
23
+ end
24
+
25
+ # tests in this context rely on sensible defaults (e.g. grep, cat are available, foo_bar_not_here is not)
26
+ context "command selection" do
27
+ it "works for empty command" do
28
+ item.command = nil
29
+
30
+ expect(item.local_command).to be_nil
31
+ end
32
+
33
+ it "does not change @command" do
34
+ item.command = [ "not_here", "cat" ]
35
+
36
+ item.local_command
37
+
38
+ expect(item.command).to eq [ "not_here", "cat" ]
39
+ end
40
+
41
+ it "works with a single correct command" do
42
+ item.command = "grep"
43
+
44
+ expect(item.local_command).to eq "grep"
45
+ end
46
+
47
+ it "works with a single wrong command" do
48
+ item.command = "foo_bar_not_here"
49
+
50
+ expect(item.local_command).to eq nil
51
+ end
52
+
53
+ it "works with a two correct commands" do
54
+ item.command = [ "grep", "cat" ]
55
+
56
+ expect(item.local_command).to eq "grep"
57
+ end
58
+
59
+ it "works with a one correct command at first position" do
60
+ item.command = [ "cat", "foo_bar_not_here" ]
61
+
62
+ expect(item.local_command).to eq "cat"
63
+ end
64
+
65
+ it "works with a one correct command at second position" do
66
+ item.command = [ "foo_bar_not_here", "cat", "foo_bar_not_here_two" ]
67
+
68
+ expect(item.local_command).to eq "cat"
69
+ end
70
+
71
+ it "does not run twice" do
72
+ item.command = [ "foo_bar_not_here", "cat" ]
73
+
74
+ expect(item.local_command).to eq "cat"
75
+
76
+ item.command = "foo_bar_not_here"
77
+
78
+ expect(item.local_command).to eq "cat"
79
+ expect(item.command).to eq "foo_bar_not_here"
80
+ end
81
+
82
+ it "runs again if reset parameter is given" do
83
+ item.command = [ "foo_bar_not_here", "cat" ]
84
+
85
+ expect(item.local_command).to eq "cat"
86
+
87
+ item.command = "grep"
88
+
89
+ expect(item.local_command(true)).to eq "grep"
90
+ end
91
+ end
92
+
93
+ # cannot cover all tests (would be 2^n test cases, n = package handler count),
94
+ # so we choose a few general ones and edge cases
95
+ context "install commands" do
96
+ it "works for no packages given" do
97
+ expect(item.install_command).to be_nil
98
+ end
99
+
100
+ it "works for custom command given" do
101
+ cmd = "my_installer -fmgu my_package"
102
+ item.install_command = cmd
103
+
104
+ expect(item.install_command).to eq cmd
105
+ end
106
+
107
+ it "works all commands given and all available" do
108
+ Bindep::OS.instance_variable_set :@command_exists_cache, {
109
+ apt: true, npm: true, brew: true, yum: true, rubygem: true
110
+ }
111
+
112
+ item.apt = "p_apt"
113
+ item.npm = "p_npm"
114
+ item.yum = "p_yum"
115
+ item.brew = "p_brew"
116
+ item.rubygem = "p_gem"
117
+ item.install_command = "my package"
118
+
119
+ results = [
120
+ Bindep::OS.apt_install("p_apt"),
121
+ Bindep::OS.yum_install("p_yum"),
122
+ Bindep::OS.brew_install("p_brew"),
123
+ Bindep::OS.npm_install("p_npm"),
124
+ Bindep::OS.rubygem_install("p_gem"),
125
+ "my package",
126
+ ]
127
+
128
+ expect(item.install_command).to eq results.join("; ")
129
+ end
130
+
131
+ it "works some commands given and some available" do
132
+ Bindep::OS.instance_variable_set :@command_exists_cache, {
133
+ apt: true, npm: true, brew: false, yum: true, rubygem: false
134
+ }
135
+
136
+ item.apt = "p_apt"
137
+ item.npm = nil
138
+ item.yum = "p_yum"
139
+ item.brew = "p_brew"
140
+ item.rubygem = "p_gem"
141
+ item.install_command = nil
142
+
143
+ results = [
144
+ Bindep::OS.apt_install("p_apt"),
145
+ Bindep::OS.yum_install("p_yum"),
146
+ ]
147
+
148
+ expect(item.install_command).to eq results.join("; ")
149
+ end
150
+ end
151
+ end
@@ -0,0 +1,7 @@
1
+ require 'spec_helper'
2
+
3
+ describe 'Bindep Library' do
4
+ it 'loads the library file successfully' do
5
+ require 'bindep/library'
6
+ end
7
+ end
@@ -0,0 +1,55 @@
1
+ require "spec_helper"
2
+
3
+ describe Bindep::OS do
4
+ HAVE_LIST = {
5
+ "brew?" => "brew",
6
+ "apt?" => "apt-get",
7
+ "yum?" => "yum",
8
+ "npm?" => "npm",
9
+ "rubygem?" => "gem",
10
+ }
11
+
12
+ INSTALL_LIST = {
13
+ "brew_install" => "brew install pkg",
14
+ "apt_install" => "apt-get install -y pkg",
15
+ "yum_install" => "yum install -y pkg",
16
+ "npm_install" => "npm install -g pkg",
17
+ "rubygem_install" => "gem install pkg",
18
+ }
19
+
20
+ before :each do
21
+ Bindep::OS.instance_variable_set(:@command_exists_cache, {})
22
+ end
23
+
24
+ HAVE_LIST.each_pair do |method, command|
25
+ it "has a #{method} method which caches result" do
26
+ expect(Bindep::Helpers).to receive(:command_exists?).with(command).once.and_return(false)
27
+
28
+ 2.times { Bindep::OS.send method.to_sym }
29
+ end
30
+ end
31
+
32
+ [ true, false ].each do |sudo|
33
+ sudo_string = sudo ? "sudo" : ""
34
+
35
+ INSTALL_LIST.each_pair do |method, command|
36
+ it "has a corrent #{method} method with sudo #{sudo}" do
37
+ expect(Bindep::OS).to receive(:sudo).and_return(sudo_string)
38
+
39
+ expect(Bindep::OS.send(method.to_sym, "pkg")).to eq "#{sudo_string} #{command}".strip
40
+ end
41
+ end
42
+ end
43
+
44
+ it "requires sudo if no brew is available (e.g. not on mac os)" do
45
+ expect(Bindep::OS).to receive(:brew?).and_return(false)
46
+
47
+ expect(Bindep::OS.sudo).to eq "sudo"
48
+ end
49
+
50
+ it "requires no sudo if brew is available" do
51
+ expect(Bindep::OS).to receive(:brew?).and_return(true)
52
+
53
+ expect(Bindep::OS.sudo).to eq ""
54
+ end
55
+ end
@@ -0,0 +1,8 @@
1
+ require "simplecov"
2
+
3
+ SimpleCov.coverage_dir "coverage"
4
+ SimpleCov.start
5
+
6
+ require 'tempfile'
7
+
8
+ require "bindep"
metadata ADDED
@@ -0,0 +1,146 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: bindep
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Niko Dziemba
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-06-10 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ! '>='
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ! '>='
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ! '>='
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ! '>='
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rspec
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ! '>='
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ! '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: guard-rspec
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ! '>='
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: simplecov
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ! '>='
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ! '>='
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ description: A simple way to manage binary dependencies for multiple platforms.
84
+ email:
85
+ - niko@dziemba.com
86
+ executables:
87
+ - bindep
88
+ extensions: []
89
+ extra_rdoc_files: []
90
+ files:
91
+ - .gitignore
92
+ - .travis.yml
93
+ - Gemfile
94
+ - Guardfile
95
+ - LICENSE
96
+ - README.md
97
+ - bin/bindep
98
+ - bindep.gemspec
99
+ - lib/bindep.rb
100
+ - lib/bindep/context.rb
101
+ - lib/bindep/core.rb
102
+ - lib/bindep/error.rb
103
+ - lib/bindep/helpers.rb
104
+ - lib/bindep/item.rb
105
+ - lib/bindep/library.rb
106
+ - lib/bindep/os.rb
107
+ - lib/bindep/version.rb
108
+ - spec/bindep/context_spec.rb
109
+ - spec/bindep/core_spec.rb
110
+ - spec/bindep/helpers_spec.rb
111
+ - spec/bindep/item_spec.rb
112
+ - spec/bindep/library_spec.rb
113
+ - spec/bindep/os_spec.rb
114
+ - spec/spec_helper.rb
115
+ homepage: https://github.com/dziemba/bindep
116
+ licenses:
117
+ - MIT
118
+ metadata: {}
119
+ post_install_message:
120
+ rdoc_options: []
121
+ require_paths:
122
+ - lib
123
+ required_ruby_version: !ruby/object:Gem::Requirement
124
+ requirements:
125
+ - - ! '>='
126
+ - !ruby/object:Gem::Version
127
+ version: '0'
128
+ required_rubygems_version: !ruby/object:Gem::Requirement
129
+ requirements:
130
+ - - ! '>='
131
+ - !ruby/object:Gem::Version
132
+ version: '0'
133
+ requirements: []
134
+ rubyforge_project:
135
+ rubygems_version: 2.2.2
136
+ signing_key:
137
+ specification_version: 4
138
+ summary: A simple way to manage binary dependencies for multiple platforms.
139
+ test_files:
140
+ - spec/bindep/context_spec.rb
141
+ - spec/bindep/core_spec.rb
142
+ - spec/bindep/helpers_spec.rb
143
+ - spec/bindep/item_spec.rb
144
+ - spec/bindep/library_spec.rb
145
+ - spec/bindep/os_spec.rb
146
+ - spec/spec_helper.rb