berkshelf 0.4.0.rc3 → 0.4.0.rc4

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.
@@ -19,7 +19,7 @@ Gem::Specification.new do |s|
19
19
  s.add_runtime_dependency 'solve', '~> 0.2.1'
20
20
  s.add_runtime_dependency 'chef', '~> 10.12.0'
21
21
  s.add_runtime_dependency 'minitar'
22
- s.add_runtime_dependency 'thor', '~> 0.15.2'
22
+ s.add_runtime_dependency 'thor', '~> 0.16.0'
23
23
 
24
24
  s.add_development_dependency 'redcarpet'
25
25
  s.add_development_dependency 'cucumber'
@@ -258,10 +258,10 @@ Feature: install cookbooks from a Berksfile
258
258
  When I run the install command
259
259
  Then the output should contain:
260
260
  """
261
- Installing artifact (0.10.0) from chef_api:
261
+ Installing artifact (0.10.2) from chef_api:
262
262
  """
263
263
  And the cookbook store should have the cookbooks:
264
- | artifact | 0.10.0 |
264
+ | artifact | 0.10.2 |
265
265
  And the exit status should be 0
266
266
 
267
267
  Scenario: with a chef_api source location specifying :knife when a Knife config is not found at the given path
@@ -0,0 +1,62 @@
1
+ Feature: --format json
2
+ As a user
3
+ I want to be able to get all output in JSON format
4
+ So I can easily parse the output in scripts
5
+
6
+ Scenario: JSON output installing a cookbook from the default location
7
+ Given I write to "Berksfile" with:
8
+ """
9
+ cookbook "mysql", "= 1.2.4"
10
+ """
11
+ When I run the install command with flags:
12
+ | --format json |
13
+ Then the output should be JSON
14
+ And the JSON at "cookbooks" should have 2 cookbooks
15
+ And the JSON at "cookbooks/0/version" should be "1.2.4"
16
+ And the JSON at "cookbooks/0/location" should be "site: 'http://cookbooks.opscode.com/api/v1/cookbooks'"
17
+
18
+ Scenario: JSON output installing a cookbook we already have
19
+ Given the cookbook store has the cookbooks:
20
+ | mysql | 1.2.4 |
21
+ And I write to "Berksfile" with:
22
+ """
23
+ cookbook "mysql", "= 1.2.4"
24
+ """
25
+ When I run the install command with flags:
26
+ | --format json |
27
+ Then the output should be JSON
28
+ And the JSON at "cookbooks" should have 1 cookbook
29
+ And the JSON at "cookbooks/0/version" should be "1.2.4"
30
+ And the JSON should not have "cookbooks/0/location"
31
+
32
+ @slow_process
33
+ Scenario: JSON output when running the upload command
34
+ Given a Berksfile with path location sources to fixtures:
35
+ | example_cookbook | example_cookbook-0.5.0 |
36
+ And the Chef server does not have the cookbooks:
37
+ | example_cookbook | 0.5.0 |
38
+ When I run the upload command with flags:
39
+ | --format json |
40
+ Then the output should be JSON
41
+ And the JSON at "cookbooks" should have 1 cookbook
42
+ And the JSON at "cookbooks/0/version" should be "0.5.0"
43
+ And the JSON should have "cookbooks/0/uploaded_to"
44
+ And the Chef server should have the cookbooks:
45
+ | example_cookbook | 0.5.0 |
46
+
47
+ Scenario: JSON output when running install command with the --shims flag
48
+ Given I write to "Berksfile" with:
49
+ """
50
+ cookbook "mysql", "1.2.4"
51
+ """
52
+ When I run the install command with flags:
53
+ | --shims |
54
+ | --format json|
55
+ Then the following directories should exist:
56
+ | cookbooks |
57
+ | cookbooks/mysql |
58
+ And the output should be JSON
59
+ And the JSON should have "shims_dir"
60
+
61
+
62
+
@@ -54,6 +54,10 @@ When /^I run the upload command$/ do
54
54
  run_simple(unescape("berks upload"), true)
55
55
  end
56
56
 
57
+ When /^I run the upload command with flags:$/ do |flags|
58
+ run_simple(unescape("berks upload #{flags.raw.join(" ")}"), false)
59
+ end
60
+
57
61
  When /^I run the cookbook command to create "(.*?)"$/ do |name|
58
62
  run_simple(unescape("berks cookbook #{name}"))
59
63
  end
@@ -0,0 +1,3 @@
1
+ Then /^the output should be JSON$/ do
2
+ lambda { parse_json(all_output) }.should_not raise_error
3
+ end
@@ -1,6 +1,7 @@
1
1
  require 'rubygems'
2
2
  require 'bundler'
3
3
  require 'spork'
4
+ require "json_spec/cucumber"
4
5
 
5
6
  Spork.prefork do
6
7
  require 'rspec'
@@ -51,6 +52,11 @@ Spork.prefork do
51
52
  def fixtures_path
52
53
  app_root_path.join('spec/fixtures')
53
54
  end
55
+
56
+ # Set the output json_spec will parse for testing JSON responses
57
+ def last_json
58
+ all_output
59
+ end
54
60
  end
55
61
 
56
62
  Spork.each_run do
@@ -16,7 +16,7 @@ Feature: update
16
16
  When I run the update command
17
17
  Then the file "Berksfile.lock" should contain exactly:
18
18
  """
19
- cookbook 'mysql', :locked_version => '1.2.6'
19
+ cookbook 'mysql', :locked_version => '1.3.0'
20
20
  cookbook 'openssl', :locked_version => '1.0.0'
21
21
  cookbook 'windows', :locked_version => '1.3.2'
22
22
  cookbook 'chef_handler', :locked_version => '1.0.6'
@@ -107,6 +107,33 @@ module Berkshelf
107
107
  end
108
108
  end
109
109
 
110
+ # Get the appropriate Formatter object based on the formatter
111
+ # classes that have been registered.
112
+ #
113
+ # @return [~Formatter]
114
+ def formatter
115
+ @formatter ||= (formatters.has_key?(@_format) ? formatters[@_format] : Formatters::HumanReadable).new
116
+ end
117
+
118
+ # Specify a formatter identifier
119
+ #
120
+ # @param [String] format
121
+ # which formatter to use
122
+ #
123
+ # @example Berkshelf.set_format "json"
124
+ def set_format(format)
125
+ @_format = format
126
+ @formatter = nil
127
+ end
128
+
129
+ # Access the formatters map that links string symbols to Formatter
130
+ # implementations
131
+ #
132
+ # @return [Hash]
133
+ def formatters
134
+ @formatters ||= {}
135
+ end
136
+
110
137
  private
111
138
 
112
139
  def null_stream
@@ -119,3 +146,5 @@ module Berkshelf
119
146
  end
120
147
  end
121
148
  end
149
+
150
+ require 'berkshelf/formatters'
@@ -126,7 +126,7 @@ module Berkshelf
126
126
  solution = resolver.resolve
127
127
  if options[:shims]
128
128
  write_shims(options[:shims], solution)
129
- Berkshelf.ui.info "Shims written to: '#{options[:shims]}'"
129
+ Berkshelf.formatter.shims_written options[:shims]
130
130
  end
131
131
  write_lockfile(resolver.sources) unless lockfile_present?
132
132
  end
@@ -153,7 +153,7 @@ module Berkshelf
153
153
  solution = resolve(options)
154
154
 
155
155
  solution.each do |cb|
156
- Berkshelf.ui.info "Uploading #{cb.cookbook_name} (#{cb.version}) to: '#{chef_server_url}'"
156
+ Berkshelf.formatter.upload cb.cookbook_name, cb.version, chef_server_url
157
157
  uploader.upload!(cb, options)
158
158
  end
159
159
  end
@@ -212,7 +212,7 @@ module Berkshelf
212
212
  begin
213
213
  instance_eval(content)
214
214
  rescue => e
215
- raise BerksfileReadError.new(e), "An error occurred while reading the Berksfile: #{e.message}"
215
+ raise BerksfileReadError.new(e), "An error occurred while reading the Berksfile: #{e.to_s}"
216
216
  end
217
217
  self
218
218
  end
@@ -4,11 +4,19 @@ require 'berkshelf'
4
4
  module Berkshelf
5
5
  # @author Jamie Winsor <jamie@vialstudios.com>
6
6
  class Cli < Thor
7
+ class << self
8
+ def dispatch(meth, given_args, given_opts, config)
9
+ super
10
+ Berkshelf.formatter.cleanup_hook unless config[:current_task].name == "help"
11
+ end
12
+ end
13
+
7
14
  def initialize(*)
8
15
  super
9
16
  # JW TODO: Replace Chef::Knife::UI with our own UI class
10
17
  ::Berkshelf.ui = Chef::Knife::UI.new(STDOUT, STDERR, STDIN, {})
11
18
  ::Berkshelf.config_path = @options[:config]
19
+ ::Berkshelf.set_format @options[:format]
12
20
  @options = options.dup # unfreeze frozen options Hash from Thor
13
21
  end
14
22
 
@@ -26,6 +34,11 @@ module Berkshelf
26
34
  desc: "Path to Knife or Chef configuration to use.",
27
35
  aliases: "-c",
28
36
  banner: "PATH"
37
+ class_option :format,
38
+ type: :string,
39
+ desc: "Output format to use.",
40
+ aliases: "-F",
41
+ banner: "FORMAT"
29
42
 
30
43
  method_option :shims,
31
44
  type: :string,
@@ -44,7 +57,7 @@ module Berkshelf
44
57
  desc: "Path to a Berksfile to operate off of.",
45
58
  aliases: "-b",
46
59
  banner: "PATH"
47
- desc "install", "Install the Cookbooks specified by a Berksfile or a Berskfile.lock."
60
+ desc "install", "Install the Cookbooks specified by a Berksfile or a Berksfile.lock."
48
61
  def install
49
62
  berksfile = ::Berkshelf::Berksfile.from_file(options[:berksfile])
50
63
  berksfile.install(options)
@@ -102,14 +115,14 @@ module Berkshelf
102
115
 
103
116
  ::Berkshelf::InitGenerator.new([path], options).invoke_all
104
117
 
105
- ::Berkshelf.ui.info "Successfully initialized"
118
+ ::Berkshelf.formatter.msg "Successfully initialized"
106
119
  end
107
120
 
108
121
  desc "version", "Display version and copyright information"
109
122
  def version
110
- Berkshelf.ui.info version_header
111
- Berkshelf.ui.info "\n"
112
- Berkshelf.ui.info license
123
+ Berkshelf.formatter.msg version_header
124
+ Berkshelf.formatter.msg "\n"
125
+ Berkshelf.formatter.msg license
113
126
  end
114
127
 
115
128
  method_option :vagrant,
@@ -12,6 +12,8 @@ module Berkshelf
12
12
  end
13
13
 
14
14
  class InternalError < BerkshelfError; status_code(99); end
15
+ class MethodNotImplmentedError < ::Berkshelf::InternalError ; end
16
+
15
17
  class BerksfileNotFound < BerkshelfError; status_code(100); end
16
18
  class NoVersionForConstraints < BerkshelfError; status_code(101); end
17
19
  class DownloadFailure < BerkshelfError; status_code(102); end
@@ -60,5 +62,15 @@ module Berkshelf
60
62
 
61
63
  class ConstraintNotSatisfied < BerkshelfError; status_code(111); end
62
64
  class InvalidChefAPILocation < BerkshelfError; status_code(112); end
63
- class BerksfileReadError < BerkshelfError; status_code(113); end
65
+ class BerksfileReadError < BerkshelfError
66
+ def initialize(original_error)
67
+ @original_error = original_error
68
+ end
69
+
70
+ status_code(113)
71
+
72
+ def status_code
73
+ @original_error ? @original_error.status_code : 113
74
+ end
75
+ end
64
76
  end
@@ -0,0 +1,41 @@
1
+ module Berkshelf
2
+ module Formatters
3
+ # @abstract Include and override {#install} {#use} {#upload}
4
+ # {#shims_written} {#msg} {#error} to implement.
5
+ #
6
+ # Implement {#cleanup_hook} to run any steps required to run after the task is finished
7
+ module AbstractFormatter
8
+ def cleanup_hook
9
+ # run after the task is finished
10
+ end
11
+
12
+ def install(cookbook, version, location)
13
+ raise MethodNotImplmentedError, "#install must be implemented on #{self.class}"
14
+ end
15
+
16
+ def use(cookbook, version, path = nil)
17
+ raise MethodNotImplmentedError, "#install must be implemented on #{self.class}"
18
+ end
19
+
20
+ def upload(cookbook, version, chef_server_url)
21
+ raise MethodNotImplmentedError, "#upload must be implemented on #{self.class}"
22
+ end
23
+
24
+ def shims_written(directory)
25
+ raise MethodNotImplmentedError, "#shims_written must be implemented on #{self.class}"
26
+ end
27
+
28
+ def msg(message)
29
+ raise MethodNotImplmentedError, "#msg must be implemented on #{self.class}"
30
+ end
31
+
32
+ def error(message)
33
+ raise MethodNotImplmentedError, "#error must be implemented on #{self.class}"
34
+ end
35
+ end
36
+ end
37
+ end
38
+
39
+ Dir["#{File.dirname(__FILE__)}/formatters/*.rb"].sort.each do |path|
40
+ require "berkshelf/formatters/#{File.basename(path, '.rb')}"
41
+ end
@@ -0,0 +1,33 @@
1
+ module Berkshelf
2
+ module Formatters
3
+ class HumanReadable
4
+ include AbstractFormatter
5
+
6
+ Berkshelf.formatters["human"] = self
7
+
8
+ def install(cookbook, version, location)
9
+ Berkshelf.ui.info "Installing #{cookbook} (#{version}) from #{location}"
10
+ end
11
+
12
+ def use(cookbook, version, path=nil)
13
+ Berkshelf.ui.info "Using #{cookbook} (#{version})#{' at '+path if path}"
14
+ end
15
+
16
+ def upload(cookbook, version, chef_server_url)
17
+ Berkshelf.ui.info "Uploading #{cookbook} (#{version}) to: '#{chef_server_url}'"
18
+ end
19
+
20
+ def shims_written(directory)
21
+ Berkshelf.ui.info "Shims written to: '#{directory}'"
22
+ end
23
+
24
+ def msg(message)
25
+ Berkshelf.ui.info message
26
+ end
27
+
28
+ def error(message)
29
+ Berkshelf.ui.error message
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,53 @@
1
+ module Berkshelf
2
+ module Formatters
3
+ class JSON
4
+ include AbstractFormatter
5
+
6
+ Berkshelf.formatters["json"] = self
7
+
8
+ def initialize
9
+ @output = {cookbooks: [], errors: [], messages: []}
10
+ @cookbooks = {}
11
+ super
12
+ end
13
+
14
+ def cleanup_hook
15
+ @cookbooks.each do |name, details|
16
+ details[:name] = name
17
+ @output[:cookbooks] << details
18
+ end
19
+ print @output.to_json
20
+ end
21
+
22
+ def install(cookbook, version, location)
23
+ @cookbooks[cookbook] ||= {}
24
+ @cookbooks[cookbook][:version] = version
25
+ @cookbooks[cookbook][:location] = location
26
+ end
27
+
28
+ def use(cookbook, version, path=nil)
29
+ @cookbooks[cookbook] ||= {}
30
+ @cookbooks[cookbook][:version] = version
31
+ @cookbooks[cookbook][:location] = path if path
32
+ end
33
+
34
+ def upload(cookbook, version, chef_server_url)
35
+ @cookbooks[cookbook] ||= {}
36
+ @cookbooks[cookbook][:version] = version
37
+ @cookbooks[cookbook][:uploaded_to] = chef_server_url
38
+ end
39
+
40
+ def shims_written(directory)
41
+ @output[:shims_dir] = directory
42
+ end
43
+
44
+ def msg(message)
45
+ @output[:messages] << message
46
+ end
47
+
48
+ def error(message)
49
+ @output[:errors] << message
50
+ end
51
+ end
52
+ end
53
+ end
@@ -126,7 +126,7 @@ module Berkshelf
126
126
  # @return [Boolean]
127
127
  def install_source(source)
128
128
  downloader.download!(source)
129
- Berkshelf.ui.info "Installing #{source.name} (#{source.cached_cookbook.version}) from #{source.location}"
129
+ Berkshelf.formatter.install source.name, source.cached_cookbook.version, source.location
130
130
  end
131
131
 
132
132
  # Use the given source to create a constraint solution if the source has been downloaded or can
@@ -158,9 +158,8 @@ module Berkshelf
158
158
  get_source(source).cached_cookbook = cached
159
159
  end
160
160
 
161
- msg = "Using #{cached.cookbook_name} (#{cached.version})"
162
- msg << " at #{source.location}" if source.location.is_a?(CookbookSource::PathLocation)
163
- Berkshelf.ui.info msg
161
+ path = source.location.is_a?(CookbookSource::PathLocation) ? "#{source.location}" : nil
162
+ Berkshelf.formatter.use cached.cookbook_name, cached.version, path
164
163
 
165
164
  true
166
165
  end
@@ -1,3 +1,3 @@
1
1
  module Berkshelf
2
- VERSION = "0.4.0.rc3"
2
+ VERSION = "0.4.0.rc4"
3
3
  end
@@ -1,5 +1,5 @@
1
1
  cookbook 'nginx', :locked_version => '0.101.0'
2
- cookbook 'build-essential', :locked_version => '1.0.2'
2
+ cookbook 'build-essential', :locked_version => '1.1.0'
3
3
  cookbook 'runit', :locked_version => '0.15.0'
4
- cookbook 'bluepill', :locked_version => '1.0.4'
4
+ cookbook 'bluepill', :locked_version => '1.0.6'
5
5
  cookbook 'ohai', :locked_version => '1.0.2'
@@ -0,0 +1,24 @@
1
+ require 'spec_helper'
2
+
3
+ module Berkshelf
4
+ module Formatters
5
+ class TestFormatter
6
+ include AbstractFormatter
7
+ end
8
+
9
+ describe AbstractFormatter do
10
+
11
+ subject { TestFormatter.new }
12
+
13
+ it "has abstract methods for all the messaging modes" do
14
+ lambda { subject.install("my_coobook","1.2.3","http://community") }.should raise_error(MethodNotImplmentedError)
15
+ lambda { subject.use("my_coobook","1.2.3") }.should raise_error(MethodNotImplmentedError)
16
+ lambda { subject.use("my_coobook","1.2.3","http://community") }.should raise_error(MethodNotImplmentedError)
17
+ lambda { subject.upload("my_coobook","1.2.3","http://chef_server") }.should raise_error(MethodNotImplmentedError)
18
+ lambda { subject.shims_written("/Users/jcocktosten") }.should raise_error(MethodNotImplmentedError)
19
+ lambda { subject.msg("something you should know") }.should raise_error(MethodNotImplmentedError)
20
+ lambda { subject.error("whoa this is bad") }.should raise_error(MethodNotImplmentedError)
21
+ end
22
+ end
23
+ end
24
+ end
@@ -14,8 +14,8 @@ describe Berkshelf::Lockfile do
14
14
  Berkshelf::Lockfile.new(resolver.sources).write
15
15
 
16
16
  File.read('Berksfile.lock').split(/\r?\n/).sort.should == [
17
- "cookbook 'bluepill', :locked_version => '1.0.4'",
18
- "cookbook 'build-essential', :locked_version => '1.0.2'",
17
+ "cookbook 'bluepill', :locked_version => '1.0.6'",
18
+ "cookbook 'build-essential', :locked_version => '1.1.0'",
19
19
  "cookbook 'nginx', :locked_version => '0.101.0'",
20
20
  "cookbook 'ohai', :locked_version => '1.0.2'",
21
21
  "cookbook 'runit', :locked_version => '0.15.0'"
@@ -45,5 +45,32 @@ describe Berkshelf do
45
45
  subject.load_config
46
46
  end
47
47
  end
48
+
49
+ describe "::formatter" do
50
+ context "with default formatter" do
51
+ it "should be human readable" do
52
+ Berkshelf.formatter.should be_an_instance_of(Berkshelf::Formatters::HumanReadable)
53
+ end
54
+ end
55
+
56
+ context "with a custom formatter" do
57
+ before(:all) do
58
+ Berkshelf.instance_eval { @formatter = nil }
59
+ end
60
+
61
+ class CustomFormatter
62
+ include Berkshelf::Formatters::AbstractFormatter
63
+ Berkshelf.formatters["custom"] = self
64
+ end
65
+
66
+ before do
67
+ Berkshelf.set_format "custom"
68
+ end
69
+
70
+ it "should be the custom class" do
71
+ Berkshelf.formatter.should be_an_instance_of(CustomFormatter)
72
+ end
73
+ end
74
+ end
48
75
  end
49
76
  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: 0.4.0.rc3
4
+ version: 0.4.0.rc4
5
5
  prerelease: 6
6
6
  platform: ruby
7
7
  authors:
@@ -12,7 +12,7 @@ authors:
12
12
  autorequire:
13
13
  bindir: bin
14
14
  cert_chain: []
15
- date: 2012-08-20 00:00:00.000000000 Z
15
+ date: 2012-08-21 00:00:00.000000000 Z
16
16
  dependencies:
17
17
  - !ruby/object:Gem::Dependency
18
18
  name: solve
@@ -69,7 +69,7 @@ dependencies:
69
69
  requirements:
70
70
  - - ~>
71
71
  - !ruby/object:Gem::Version
72
- version: 0.15.2
72
+ version: 0.16.0
73
73
  type: :runtime
74
74
  prerelease: false
75
75
  version_requirements: !ruby/object:Gem::Requirement
@@ -77,7 +77,7 @@ dependencies:
77
77
  requirements:
78
78
  - - ~>
79
79
  - !ruby/object:Gem::Version
80
- version: 0.15.2
80
+ version: 0.16.0
81
81
  - !ruby/object:Gem::Dependency
82
82
  name: redcarpet
83
83
  requirement: !ruby/object:Gem::Requirement
@@ -373,11 +373,13 @@ files:
373
373
  - features/cookbook_command.feature
374
374
  - features/init_command.feature
375
375
  - features/install.feature
376
+ - features/json_formatter.feature
376
377
  - features/lockfile.feature
377
378
  - features/step_definitions/berksfile_steps.rb
378
379
  - features/step_definitions/chef_server_steps.rb
379
380
  - features/step_definitions/cli_steps.rb
380
381
  - features/step_definitions/filesystem_steps.rb
382
+ - features/step_definitions/json_steps.rb
381
383
  - features/support/env.rb
382
384
  - features/update.feature
383
385
  - features/upload_command.feature
@@ -418,6 +420,9 @@ files:
418
420
  - lib/berkshelf/downloader.rb
419
421
  - lib/berkshelf/dsl.rb
420
422
  - lib/berkshelf/errors.rb
423
+ - lib/berkshelf/formatters.rb
424
+ - lib/berkshelf/formatters/human_readable.rb
425
+ - lib/berkshelf/formatters/json.rb
421
426
  - lib/berkshelf/git.rb
422
427
  - lib/berkshelf/init_generator.rb
423
428
  - lib/berkshelf/lockfile.rb
@@ -431,6 +436,7 @@ files:
431
436
  - spec/fixtures/cookbooks/example_cookbook-0.5.0/README.md
432
437
  - spec/fixtures/cookbooks/example_cookbook-0.5.0/metadata.rb
433
438
  - spec/fixtures/cookbooks/example_cookbook-0.5.0/recipes/default.rb
439
+ - spec/fixtures/cookbooks/example_cookbook/Berksfile.lock
434
440
  - spec/fixtures/cookbooks/example_cookbook/README.md
435
441
  - spec/fixtures/cookbooks/example_cookbook/metadata.rb
436
442
  - spec/fixtures/cookbooks/example_cookbook/recipes/default.rb
@@ -471,6 +477,7 @@ files:
471
477
  - spec/unit/berkshelf/core_ext/fileutils_spec.rb
472
478
  - spec/unit/berkshelf/downloader_spec.rb
473
479
  - spec/unit/berkshelf/dsl_spec.rb
480
+ - spec/unit/berkshelf/formatters_spec.rb
474
481
  - spec/unit/berkshelf/git_spec.rb
475
482
  - spec/unit/berkshelf/init_generator_spec.rb
476
483
  - spec/unit/berkshelf/lockfile_spec.rb
@@ -507,11 +514,13 @@ test_files:
507
514
  - features/cookbook_command.feature
508
515
  - features/init_command.feature
509
516
  - features/install.feature
517
+ - features/json_formatter.feature
510
518
  - features/lockfile.feature
511
519
  - features/step_definitions/berksfile_steps.rb
512
520
  - features/step_definitions/chef_server_steps.rb
513
521
  - features/step_definitions/cli_steps.rb
514
522
  - features/step_definitions/filesystem_steps.rb
523
+ - features/step_definitions/json_steps.rb
515
524
  - features/support/env.rb
516
525
  - features/update.feature
517
526
  - features/upload_command.feature
@@ -520,6 +529,7 @@ test_files:
520
529
  - spec/fixtures/cookbooks/example_cookbook-0.5.0/README.md
521
530
  - spec/fixtures/cookbooks/example_cookbook-0.5.0/metadata.rb
522
531
  - spec/fixtures/cookbooks/example_cookbook-0.5.0/recipes/default.rb
532
+ - spec/fixtures/cookbooks/example_cookbook/Berksfile.lock
523
533
  - spec/fixtures/cookbooks/example_cookbook/README.md
524
534
  - spec/fixtures/cookbooks/example_cookbook/metadata.rb
525
535
  - spec/fixtures/cookbooks/example_cookbook/recipes/default.rb
@@ -560,6 +570,7 @@ test_files:
560
570
  - spec/unit/berkshelf/core_ext/fileutils_spec.rb
561
571
  - spec/unit/berkshelf/downloader_spec.rb
562
572
  - spec/unit/berkshelf/dsl_spec.rb
573
+ - spec/unit/berkshelf/formatters_spec.rb
563
574
  - spec/unit/berkshelf/git_spec.rb
564
575
  - spec/unit/berkshelf/init_generator_spec.rb
565
576
  - spec/unit/berkshelf/lockfile_spec.rb