berkshelf 2.0.1 → 2.0.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.
@@ -1,3 +1,14 @@
1
+ # 2.0.3
2
+
3
+ * Fix issue where groups defined in the Berksfile would not be evaluated
4
+
5
+ # 2.0.2
6
+
7
+ * Fix issue with shellout on Windows. This would effect uploads and downloads of cookbooks using the Git location.
8
+ * The Berksfile DSL now evaluates in a clean room to prevent end-users from calling restricted methods.
9
+ * Fix issue with `berks upload -D` not properly skipping dependencies
10
+ * Added friendly error message when an unknown license is chosen during cookbook generation
11
+
1
12
  # 2.0.1
2
13
 
3
14
  * Improve performance of `berks upload`. It will now properly respect the Lockfile
@@ -38,7 +38,7 @@ Gem::Specification.new do |s|
38
38
  s.add_dependency 'hashie', '>= 2.0.2'
39
39
  s.add_dependency 'minitar', '~> 0.5.4'
40
40
  s.add_dependency 'retryable', '~> 1.3.3'
41
- s.add_dependency 'ridley', '~> 1.0.0'
41
+ s.add_dependency 'ridley', '~> 1.0.2'
42
42
  s.add_dependency 'solve', '>= 0.4.4'
43
43
  s.add_dependency 'test-kitchen', '>= 1.0.0.alpha7'
44
44
  s.add_dependency 'thor', '~> 0.18.0'
@@ -263,3 +263,34 @@ Feature: Uploading cookbooks to a Chef Server
263
263
  The cookbook 'cookbook with spaces' has invalid filenames:
264
264
  """
265
265
  And the CLI should exit with the status code for error "InvalidCookbookFiles"
266
+
267
+ @chef_server @slow_process
268
+ Scenario: With the --skip-dependencies flag
269
+ Given the cookbook store has the cookbooks:
270
+ | fake | 1.0.0 |
271
+ | ekaf | 2.0.0 |
272
+ And the cookbook store contains a cookbook "reset" "3.4.5" with dependencies:
273
+ | fake | ~> 1.0.0 |
274
+ And I write to "Berksfile" with:
275
+ """
276
+ cookbook 'fake', '1.0.0'
277
+ cookbook 'ekaf', '2.0.0'
278
+ cookbook 'reset', '3.4.5'
279
+ """
280
+ And the Chef server does not have the cookbooks:
281
+ | fake | 1.0.0 |
282
+ | ekaf | 2.0.0 |
283
+ | reset | 3.4.5 |
284
+ When I successfully run `berks upload reset -D`
285
+ Then the output should contain:
286
+ """
287
+ Uploading reset (3.4.5) to: 'http://localhost:4000/'
288
+ Uploading fake (1.0.0) to: 'http://localhost:4000/'
289
+ """
290
+ And the Chef server should have the cookbooks:
291
+ | reset | 3.4.5 |
292
+ | fake | 1.0.0 |
293
+ And the Chef server should not have the cookbooks:
294
+ | ekaf | 2.0.0 |
295
+ And the exit status should be 0
296
+
@@ -14,9 +14,10 @@ require 'tmpdir'
14
14
  require 'uri'
15
15
  require 'zlib'
16
16
 
17
- require 'berkshelf/core_ext'
18
- require 'berkshelf/errors'
19
- require 'thor/monkies'
17
+ require_relative 'berkshelf/core_ext'
18
+ require_relative 'berkshelf/errors'
19
+ require_relative 'berkshelf/mixin'
20
+ require_relative 'berkshelf/thor_ext'
20
21
 
21
22
  JSON.create_id = nil
22
23
 
@@ -24,7 +25,6 @@ module Berkshelf
24
25
  DEFAULT_FILENAME = 'Berksfile'.freeze
25
26
 
26
27
  class << self
27
- require 'berkshelf/mixin/logging'
28
28
  include Berkshelf::Mixin::Logging
29
29
 
30
30
  attr_accessor :ui
@@ -160,4 +160,4 @@ require_relative 'berkshelf/ui'
160
160
  require_relative 'berkshelf/version'
161
161
 
162
162
  Ridley.logger = Celluloid.logger = Berkshelf.logger = Logger.new(STDOUT)
163
- Berkshelf.logger.level = Logger::WARN
163
+ Berkshelf.logger.level = Logger::WARN
@@ -1,21 +1,16 @@
1
1
  module Berkshelf
2
2
  class Berksfile
3
- require 'berkshelf/mixin/logging'
4
- include Berkshelf::Mixin::Logging
5
-
6
- extend Forwardable
7
-
8
3
  class << self
9
- # @param [String] file
4
+ # @param [#to_s] file
10
5
  # a path on disk to a Berksfile to instantiate from
11
6
  #
12
7
  # @return [Berksfile]
13
8
  def from_file(file)
14
- content = File.read(file)
15
- object = new(file)
16
- object.load(content)
17
- rescue Errno::ENOENT => e
9
+ new(file).dsl_eval_file(file)
10
+ rescue Errno::ENOENT => ex
18
11
  raise BerksfileNotFound, "No Berksfile or Berksfile.lock found at: #{file}"
12
+ rescue => ex
13
+ raise BerksfileReadError.new(ex)
19
14
  end
20
15
 
21
16
  # Copy all cached_cookbooks to the given directory. Each cookbook will be contained in
@@ -60,6 +55,16 @@ module Berkshelf
60
55
  end
61
56
  end
62
57
 
58
+ include Berkshelf::Mixin::Logging
59
+ include Berkshelf::Mixin::DSLEval
60
+ extend Forwardable
61
+
62
+ expose_method :metadata
63
+ expose_method :group
64
+ expose_method :site
65
+ expose_method :chef_api
66
+ expose_method :cookbook
67
+
63
68
  @@active_group = nil
64
69
 
65
70
  # @return [String]
@@ -549,7 +554,7 @@ module Berkshelf
549
554
  end
550
555
 
551
556
  if options[:skip_dependencies]
552
- missing_cookbooks = options.fetch(:cookbooks, nil) - solution.map(&:cookbook_name)
557
+ missing_cookbooks = options.fetch(:cookbooks, nil) - cached_cookbooks.map(&:cookbook_name)
553
558
  unless missing_cookbooks.empty?
554
559
  msg = "Unable to upload cookbooks: #{missing_cookbooks.sort.join(', ')}\n"
555
560
  msg << "Specified cookbooks must be defined within the Berkshelf file when using the"
@@ -681,23 +686,6 @@ module Berkshelf
681
686
  { solution: resolver.resolve, sources: resolver.sources }
682
687
  end
683
688
 
684
- # Reload this instance of Berksfile with the given content. The content
685
- # is a string that may contain terms from the included DSL.
686
- #
687
- # @param [String] content
688
- #
689
- # @raise [BerksfileReadError] if Berksfile contains bad content
690
- #
691
- # @return [Berksfile]
692
- def load(content)
693
- begin
694
- instance_eval(content)
695
- rescue => e
696
- raise BerksfileReadError.new(e)
697
- end
698
- self
699
- end
700
-
701
689
  # Get the lockfile corresponding to this Berksfile. This is necessary because
702
690
  # the user can specify a different path to the Berksfile. So assuming the lockfile
703
691
  # is named "Berksfile.lock" is a poor assumption.
@@ -2,6 +2,14 @@ module Berkshelf
2
2
  class CookbookGenerator < BaseGenerator
3
3
  require_relative 'config'
4
4
 
5
+ LICENSES = [
6
+ "apachev2",
7
+ "gplv2",
8
+ "gplv3",
9
+ "mit",
10
+ "reserved"
11
+ ].freeze
12
+
5
13
  argument :name,
6
14
  type: :string,
7
15
  required: true
@@ -79,7 +87,7 @@ module Berkshelf
79
87
  when 'mit'; 'MIT'
80
88
  when 'reserved'; 'All rights reserved'
81
89
  else
82
- raise Berkshelf::InternalError, "Unknown license: '#{options[:license]}'"
90
+ raise Berkshelf::LicenseNotFound.new(options[:license])
83
91
  end
84
92
  end
85
93
 
@@ -95,7 +103,7 @@ module Berkshelf
95
103
  when 'mit'; 'licenses/mit.erb'
96
104
  when 'reserved'; 'licenses/reserved.erb'
97
105
  else
98
- raise Berkshelf::InternalError, "Unknown license: '#{options[:license]}'"
106
+ raise Berkshelf::LicenseNotFound.new(options[:license])
99
107
  end
100
108
  end
101
109
 
@@ -185,7 +185,6 @@ module Berkshelf
185
185
 
186
186
  class ConfigExists < BerkshelfError; status_code(116); end
187
187
  class ConfigurationError < BerkshelfError; status_code(117); end
188
- class CommandUnsuccessful < BerkshelfError; status_code(118); end
189
188
  class InsufficientPrivledges < BerkshelfError; status_code(119); end
190
189
  class ExplicitCookbookNotFound < BerkshelfError; status_code(120); end
191
190
  class ValidationFailed < BerkshelfError; status_code(121); end
@@ -340,10 +339,25 @@ module Berkshelf
340
339
  end
341
340
  end
342
341
 
342
+ class LicenseNotFound < BerkshelfError
343
+ status_code(134)
344
+
345
+ attr_reader :license
346
+
347
+ def initialize(license)
348
+ @license = license
349
+ end
350
+
351
+ def to_s
352
+ "Unknown license: '#{license}'\n" +
353
+ "Available licenses: #{Berkshelf::CookbookGenerator::LICENSES.join(', ')}"
354
+ end
355
+ end
356
+
343
357
  # Raised when a cookbook or its recipes contain a space or invalid
344
358
  # character in the path.
345
359
  class ConfigNotFound < BerkshelfError
346
- status_code(133)
360
+ status_code(135)
347
361
 
348
362
  # @param [String] type
349
363
  # the type of config that was not found (Berkshelf, Chef, etc)
@@ -2,9 +2,6 @@ require 'uri'
2
2
 
3
3
  module Berkshelf
4
4
  class Git
5
- require 'berkshelf/mixin/shellout'
6
- extend Berkshelf::Mixin::Shellout
7
-
8
5
  GIT_REGEXP = URI.regexp(%w(http https ssh git+ssh git rsync))
9
6
  SCP_REGEXP = /^(.+@)?[\w\d\.-]+:.*$/
10
7
 
@@ -12,6 +9,8 @@ module Berkshelf
12
9
  HAS_SPACE_RE = %r{\s}.freeze
13
10
 
14
11
  class << self
12
+ include Ridley::Mixin::ShellOut
13
+
15
14
  # @overload git(commands)
16
15
  # Shellout to the Git executable on your system with the given commands.
17
16
  #
@@ -22,13 +21,13 @@ module Berkshelf
22
21
  def git(*command)
23
22
  command.unshift(git_cmd)
24
23
  command_str = command.map { |p| quote_cmd_arg(p) }.join(' ')
25
- result = shellout(command_str)
24
+ response = shell_out(command_str)
26
25
 
27
- unless result.success?
28
- raise GitError.new(result.stderr)
26
+ unless response.success?
27
+ raise GitError.new(response.stderr.strip)
29
28
  end
30
29
 
31
- result.stdout
30
+ response.stdout.strip
32
31
  end
33
32
 
34
33
  # Clone a remote Git repository to disk
@@ -0,0 +1,7 @@
1
+ module Berkshelf
2
+ module Mixin; end
3
+ end
4
+
5
+ Dir["#{File.dirname(__FILE__)}/mixin/*.rb"].sort.each do |path|
6
+ require_relative "mixin/#{File.basename(path, '.rb')}"
7
+ end
@@ -0,0 +1,58 @@
1
+ module Berkshelf
2
+ module Mixin
3
+ module DSLEval
4
+ class CleanRoom
5
+ attr_reader :instance
6
+
7
+ def initialize(instance)
8
+ @instance = instance
9
+ end
10
+ end
11
+
12
+ class << self
13
+ def included(base)
14
+ base.send(:extend, ClassMethods)
15
+ end
16
+ end
17
+
18
+ module ClassMethods
19
+ def clean_room
20
+ @clean_room ||= begin
21
+ exposed_methods = self.exposed_methods
22
+
23
+ Class.new(DSLEval::CleanRoom) do
24
+ exposed_methods.each do |exposed_method|
25
+ define_method(exposed_method) do |*args, &block|
26
+ instance.send(exposed_method, *args, &block)
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
32
+
33
+ def expose_method(method)
34
+ exposed_methods << method.to_sym
35
+ end
36
+
37
+ def exposed_methods
38
+ @exposed_methods ||= Array.new
39
+ end
40
+ end
41
+
42
+ # @return [Object]
43
+ def dsl_eval(&block)
44
+ self.class.clean_room.new(self).instance_eval(&block)
45
+ self
46
+ end
47
+
48
+ # @param [String] filepath
49
+ #
50
+ # @return [Object]
51
+ def dsl_eval_file(filepath)
52
+ filepath = filepath.to_s
53
+ contents = File.read(filepath)
54
+ dsl_eval { eval(contents, binding, filepath, 1) }
55
+ end
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,3 @@
1
+ Dir["#{File.dirname(__FILE__)}/thor_ext/*.rb"].sort.each do |path|
2
+ require_relative "thor_ext/#{File.basename(path, '.rb')}"
3
+ end
@@ -1,3 +1,3 @@
1
1
  module Berkshelf
2
- VERSION = '2.0.1'
2
+ VERSION = "2.0.3"
3
3
  end
@@ -2,10 +2,27 @@ require 'spec_helper'
2
2
 
3
3
  describe Berkshelf::Berksfile do
4
4
  describe '.from_file' do
5
- let(:cookbook_file) { fixtures_path.join('lockfile_spec', 'with_lock', 'Berksfile') }
5
+ let(:content) do
6
+ <<-EOF.strip
7
+ cookbook 'ntp', '<= 1.0.0'
8
+ cookbook 'mysql'
9
+ cookbook 'nginx', '< 0.101.2'
10
+ cookbook 'ssh_known_hosts2', :git => 'https://github.com/erikh/chef-ssh_known_hosts2.git'
11
+ EOF
12
+ end
13
+ let(:berksfile) { tmp_path.join('Berksfile') }
6
14
 
7
- it 'reads a Berksfile and returns an instance Berksfile' do
8
- expect(Berkshelf::Berksfile.from_file(cookbook_file)).to be_a(Berkshelf::Berksfile)
15
+ before { File.open(berksfile, 'w+') { |f| f.write(content) } }
16
+ subject(:from_file) { described_class.from_file(berksfile) }
17
+
18
+ it "reads the content of the Berksfile and binds them to a new instance" do
19
+ %w(ntp mysql nginx ssh_known_hosts2).each do |name|
20
+ expect(subject).to have_source(name)
21
+ end
22
+ end
23
+
24
+ it "returns an instance of Berkshelf::Berksfile" do
25
+ expect(subject).to be_a(described_class)
9
26
  end
10
27
 
11
28
  context 'when Berksfile does not exist at given path' do
@@ -340,29 +357,6 @@ describe Berkshelf::Berksfile do
340
357
  end
341
358
  end
342
359
 
343
- describe '#load' do
344
- let(:content) do
345
- <<-EOF.strip
346
- cookbook 'ntp', '<= 1.0.0'
347
- cookbook 'mysql'
348
- cookbook 'nginx', '< 0.101.2'
349
- cookbook 'ssh_known_hosts2', :git => 'https://github.com/erikh/chef-ssh_known_hosts2.git'
350
- EOF
351
- end
352
-
353
- it 'reads the content of a Berksfile and adds the sources to the Shelf' do
354
- subject.load(content)
355
-
356
- %w(ntp mysql nginx ssh_known_hosts2).each do |name|
357
- expect(subject).to have_source(name)
358
- end
359
- end
360
-
361
- it 'returns an instance of Berksfile' do
362
- expect(subject.load(content)).to be_a(Berkshelf::Berksfile)
363
- end
364
- end
365
-
366
360
  describe '#add_source' do
367
361
  let(:name) { 'cookbook_one' }
368
362
  let(:constraint) { '= 1.2.0' }
@@ -77,4 +77,14 @@ describe Berkshelf::CookbookGenerator do
77
77
  }
78
78
  end
79
79
  end
80
+
81
+ context "given an invalid option for :license" do
82
+ subject(:run) do
83
+ capture(:stdout) { described_class.new([target, name], license: 'not-there').invoke_all }
84
+ end
85
+
86
+ it "raises a LicenseNotFound error" do
87
+ expect { run }.to raise_error(Berkshelf::LicenseNotFound)
88
+ end
89
+ end
80
90
  end
@@ -0,0 +1,55 @@
1
+ require 'spec_helper'
2
+
3
+ describe Berkshelf::Mixin::DSLEval do
4
+ let(:klass) do
5
+ klass = Class.new
6
+ klass.send(:include, described_class)
7
+ klass
8
+ end
9
+
10
+ describe "ClassMethods" do
11
+ describe "::clean_room" do
12
+ subject { klass.clean_room }
13
+
14
+ it "returns an anonymous class inheriting from DSLEval::CleanRoom" do
15
+ expect(subject.superclass).to eql(described_class::CleanRoom)
16
+ end
17
+ end
18
+
19
+ describe "::expose_method" do
20
+ subject { klass }
21
+
22
+ it "adds a method to the exposed methods" do
23
+ klass.expose_method(:something)
24
+ expect(subject.exposed_methods).to have(1).item
25
+ end
26
+ end
27
+
28
+ describe "::exposed_methods" do
29
+ it "returns an array" do
30
+ expect(klass.exposed_methods).to be_a(Array)
31
+ end
32
+ end
33
+ end
34
+
35
+ describe "#dsl_eval" do
36
+ subject do
37
+ klass.new.dsl_eval { }
38
+ end
39
+
40
+ it "returns an instance of the including class" do
41
+ expect(subject).to be_a(klass)
42
+ end
43
+ end
44
+
45
+ describe "#dsl_eval_file" do
46
+ let(:filepath) { tmp_path.join('somefile') }
47
+ before { FileUtils.touch(filepath) }
48
+
49
+ subject { klass.new.dsl_eval_file(filepath) }
50
+
51
+ it "returns an instance of the including class" do
52
+ expect(subject).to be_a(klass)
53
+ end
54
+ end
55
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: berkshelf
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.1
4
+ version: 2.0.3
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -13,7 +13,7 @@ authors:
13
13
  autorequire:
14
14
  bindir: bin
15
15
  cert_chain: []
16
- date: 2013-06-07 00:00:00.000000000 Z
16
+ date: 2013-06-11 00:00:00.000000000 Z
17
17
  dependencies:
18
18
  - !ruby/object:Gem::Dependency
19
19
  name: activesupport
@@ -150,7 +150,7 @@ dependencies:
150
150
  requirements:
151
151
  - - ~>
152
152
  - !ruby/object:Gem::Version
153
- version: 1.0.0
153
+ version: 1.0.2
154
154
  type: :runtime
155
155
  prerelease: false
156
156
  version_requirements: !ruby/object:Gem::Requirement
@@ -158,7 +158,7 @@ dependencies:
158
158
  requirements:
159
159
  - - ~>
160
160
  - !ruby/object:Gem::Version
161
- version: 1.0.0
161
+ version: 1.0.2
162
162
  - !ruby/object:Gem::Dependency
163
163
  name: solve
164
164
  requirement: !ruby/object:Gem::Requirement
@@ -579,7 +579,6 @@ files:
579
579
  - lib/berkshelf/chef/cookbook.rb
580
580
  - lib/berkshelf/chef/cookbook/chefignore.rb
581
581
  - lib/berkshelf/cli.rb
582
- - lib/berkshelf/command.rb
583
582
  - lib/berkshelf/commands/shelf.rb
584
583
  - lib/berkshelf/commands/test_command.rb
585
584
  - lib/berkshelf/community_rest.rb
@@ -608,17 +607,18 @@ files:
608
607
  - lib/berkshelf/locations/site_location.rb
609
608
  - lib/berkshelf/lockfile.rb
610
609
  - lib/berkshelf/logger.rb
610
+ - lib/berkshelf/mixin.rb
611
611
  - lib/berkshelf/mixin/config.rb
612
+ - lib/berkshelf/mixin/dsl_eval.rb
612
613
  - lib/berkshelf/mixin/logging.rb
613
- - lib/berkshelf/mixin/shellout.rb
614
614
  - lib/berkshelf/resolver.rb
615
615
  - lib/berkshelf/test.rb
616
616
  - lib/berkshelf/thor.rb
617
+ - lib/berkshelf/thor_ext.rb
618
+ - lib/berkshelf/thor_ext/hash_with_indifferent_access.rb
619
+ - lib/berkshelf/thor_ext/shell.rb
617
620
  - lib/berkshelf/ui.rb
618
621
  - lib/berkshelf/version.rb
619
- - lib/thor/monkies.rb
620
- - lib/thor/monkies/hash_with_indifferent_access.rb
621
- - lib/thor/monkies/shell.rb
622
622
  - spec/config/berkshelf.pem
623
623
  - spec/config/knife.rb
624
624
  - spec/config/validator.pem
@@ -693,6 +693,7 @@ files:
693
693
  - spec/unit/berkshelf/locations/site_location_spec.rb
694
694
  - spec/unit/berkshelf/lockfile_spec.rb
695
695
  - spec/unit/berkshelf/logger_spec.rb
696
+ - spec/unit/berkshelf/mixin/dsl_eval_spec.rb
696
697
  - spec/unit/berkshelf/mixin/logging_spec.rb
697
698
  - spec/unit/berkshelf/resolver_spec.rb
698
699
  - spec/unit/berkshelf/ui_spec.rb
@@ -830,6 +831,7 @@ test_files:
830
831
  - spec/unit/berkshelf/locations/site_location_spec.rb
831
832
  - spec/unit/berkshelf/lockfile_spec.rb
832
833
  - spec/unit/berkshelf/logger_spec.rb
834
+ - spec/unit/berkshelf/mixin/dsl_eval_spec.rb
833
835
  - spec/unit/berkshelf/mixin/logging_spec.rb
834
836
  - spec/unit/berkshelf/resolver_spec.rb
835
837
  - spec/unit/berkshelf/ui_spec.rb
@@ -1,116 +0,0 @@
1
- module Berkshelf
2
- # This superclass is responsible for handling common command methods and options.
3
- module Command
4
- # Initialize a new instance of the parent class
5
- #
6
- # @param [Hash] options
7
- # the list of options to pass to the installer
8
- def initialize(options = {})
9
- @options = options
10
- end
11
-
12
- private
13
-
14
- # Validate the options hash, ensuring there are no conflicting arguments
15
- #
16
- # @raise [Berkshelf::ArgumentError]
17
- # if there are conflicting or invalid options
18
- def validate_options!
19
- if options[:except] && options[:only]
20
- raise Berkshelf::ArgumentError, 'Cannot specify both :except and :only'
21
- end
22
-
23
- if options[:cookbooks] && (options[:except] || options[:only])
24
- Berkshelf.ui.warn ':cookbooks were supplied to update(), so :except and :only are ignored...'
25
- end
26
- end
27
-
28
- # Ensure the berkshelf directory is created and accessible.
29
- def ensure_berkshelf_directory!
30
- unless File.exists?(Berkshelf.berkshelf_path)
31
- FileUtils.mkdir_p(Berkshelf.berkshelf_path)
32
- end
33
- end
34
-
35
- # Check for the presence of a Berksfile. Berkshelf cannot do anything
36
- # without the presence of a Berksfile.lock.
37
- def ensure_berksfile!
38
- unless File.exists?(options[:berksfile])
39
- raise Berkshelf::BerksfileNotFound, "No #{options[:berksfile]} was found at ."
40
- end
41
- end
42
-
43
- # Check that the Berksfile has content. If the Berksfile is empty, raise
44
- # an exception to require at least one definition.
45
- def ensure_berksfile_content!
46
- begin
47
- unless File.read(options[:berksfile]).size > 1
48
- raise Berkshelf::BerksfileNotFound, "Your #{options[:berksfile]} is empty! You need at least one cookbook definition."
49
- end
50
- rescue Errno::ENOENT
51
- ensure_berksfile!
52
- end
53
- end
54
-
55
- # @return [Hash]
56
- # the options for this installer
57
- def options
58
- @options ||= {}
59
- end
60
-
61
- # Attempt to load and parse the lockfile associated with this berksfile.
62
- #
63
- # @return [Berkshelf::Lockfile, nil]
64
- # the lockfile for the current berksfile
65
- def lockfile
66
- @lockfile ||= berksfile.lockfile
67
- end
68
-
69
- # Load the Berksfile for the current project.
70
- #
71
- # @raise [Berkshelf::BerksfileNotFound]
72
- # if the file is not found
73
- #
74
- # @return [Berkshelf::Berksfile]
75
- # the current Berksfile
76
- def berksfile
77
- @berksfile ||= Berkshelf::Berksfile.from_file(options[:berksfile])
78
- end
79
-
80
- # Filter the list of sources from the options passed to the installer.
81
- #
82
- # @param [Array<Berkshelf::CookbookSource>] sources
83
- # the list of sources to resolve
84
- #
85
- # @raise [Berkshelf::ArgumentError]
86
- # if a value for both :except and :only is provided
87
- #
88
- # @raise [Berkshelf::CookbookNotFound]
89
- # if a cookbook name is specified that does not exist
90
- #
91
- # @return [Array<Berkshelf::CookbookSource>]
92
- def filter(sources)
93
- cookbooks = Array(options[:cookbooks]).map(&:to_s)
94
- except = Array(options[:except]).map(&:to_sym)
95
- only = Array(options[:only]).map(&:to_sym)
96
-
97
- case
98
- when !cookbooks.empty?
99
- missing_cookbooks = (cookbooks - sources.map(&:name))
100
-
101
- unless missing_cookbooks.empty?
102
- raise Berkshelf::CookbookNotFound, "Could not find cookbooks #{missing_cookbooks.collect{|cookbook| "'#{cookbook}'"}.join(', ')} in any of the sources. #{missing_cookbooks.size == 1 ? 'Is it' : 'Are they' } in your Berksfile?"
103
- end
104
-
105
- sources.select { |source| options[:cookbooks].include?(source.name) }
106
- when !except.empty?
107
- sources.select { |source| (except & source.groups).empty? }
108
- when !only.empty?
109
- sources.select { |source| !(only & source.groups).empty? }
110
- else
111
- sources
112
- end
113
- end
114
-
115
- end
116
- end
@@ -1,71 +0,0 @@
1
- require 'hashie'
2
-
3
- module Berkshelf
4
- module Mixin
5
- module Shellout
6
- # Perform a cross-platform shell command, returning the process result.
7
- # This uses Process.spawn under the hood for Ruby 1.9, so see
8
- # {Process.spawn} for more information.
9
- #
10
- # On JRuby, a system command is used and $stdout and $stderr are captured.
11
- #
12
- # @param [String] command
13
- # @param [Hash] options
14
- # a list of options to send to {Process.spawn}
15
- # @return [Hashie::Mash]
16
- # information about the command including:
17
- # - stderr
18
- # - stdout
19
- # - exitstatus
20
- # - pid
21
- # - success?
22
- # - failure?
23
- def shellout(command)
24
- if defined?(RUBY_PLATFORM) && RUBY_PLATFORM == 'java' # jruby
25
- out, err, e = capture do
26
- system(command)
27
- end
28
- else
29
- begin
30
- out_file, err_file = Tempfile.new('berkshelf.stdout'), Tempfile.new('berkshelf.stderr')
31
- pid = Process.spawn({}, command, out: out_file.to_i, err: err_file.to_i)
32
- Process.waitpid(pid)
33
-
34
- out, err = File.read(out_file), File.read(err_file)
35
- e = $?
36
- rescue Errno::ENOENT
37
- out, err = "", "command not found: #{command}"
38
- e = $?
39
- end
40
- end
41
-
42
- Hashie::Mash.new({
43
- stdout: out.strip,
44
- stderr: err.strip,
45
- exitstatus: e.exitstatus,
46
- pid: e.pid,
47
- success?: e.success?,
48
- failure?: !e.success?
49
- })
50
- end
51
-
52
- private
53
- # Execute the given block, capturing $stdout, $stderr, and the returned process.
54
- #
55
- # @return [Array<StringIO, StringIO, Process>]
56
- # a tuple of $stdout, $stderr, and the Process
57
- def capture(&block)
58
- out, err = StringIO.new, StringIO.new
59
- $stdout, $stderr = out, err
60
-
61
- yield
62
-
63
- out.rewind
64
- err.rewind
65
- return out.read, err.read, $?
66
- ensure
67
- $stdout, $stderr = STDOUT, STDERR
68
- end
69
- end
70
- end
71
- end
@@ -1,3 +0,0 @@
1
- Dir["#{File.dirname(__FILE__)}/monkies/*.rb"].sort.each do |path|
2
- require "thor/monkies/#{File.basename(path, '.rb')}"
3
- end