berkshelf 3.0.0.beta7 → 3.0.0.beta8

Sign up to get free protection for your applications and to get access to all the features.
Files changed (94) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/.travis.yml +4 -1
  4. data/CONTRIBUTING.md +1 -1
  5. data/Gemfile +0 -1
  6. data/Guardfile +0 -8
  7. data/README.md +33 -13
  8. data/berkshelf.gemspec +3 -3
  9. data/features/commands/install.feature +16 -88
  10. data/features/commands/search.feature +15 -0
  11. data/features/commands/shelf/show.feature +2 -2
  12. data/features/commands/shelf/uninstall.feature +1 -1
  13. data/features/commands/show.feature +3 -3
  14. data/features/commands/update.feature +29 -1
  15. data/features/commands/upload.feature +172 -7
  16. data/features/commands/vendor.feature +32 -0
  17. data/features/json_formatter.feature +26 -24
  18. data/features/lifecycle.feature +285 -0
  19. data/features/lockfile.feature +9 -7
  20. data/features/step_definitions/chef_server_steps.rb +1 -0
  21. data/features/step_definitions/cli_steps.rb +2 -2
  22. data/features/step_definitions/filesystem_steps.rb +2 -4
  23. data/gem_graph.png +0 -0
  24. data/generator_files/chefignore +0 -2
  25. data/lib/berkshelf.rb +39 -14
  26. data/lib/berkshelf/berksfile.rb +161 -113
  27. data/lib/berkshelf/cached_cookbook.rb +2 -2
  28. data/lib/berkshelf/cli.rb +15 -3
  29. data/lib/berkshelf/commands/shelf.rb +3 -7
  30. data/lib/berkshelf/community_rest.rb +9 -9
  31. data/lib/berkshelf/config.rb +3 -3
  32. data/lib/berkshelf/cookbook_generator.rb +0 -8
  33. data/lib/berkshelf/cookbook_store.rb +1 -2
  34. data/lib/berkshelf/dependency.rb +25 -138
  35. data/lib/berkshelf/downloader.rb +41 -7
  36. data/lib/berkshelf/errors.rb +113 -214
  37. data/lib/berkshelf/formatters/base.rb +42 -0
  38. data/lib/berkshelf/formatters/human.rb +145 -0
  39. data/lib/berkshelf/formatters/json.rb +149 -133
  40. data/lib/berkshelf/formatters/null.rb +8 -18
  41. data/lib/berkshelf/init_generator.rb +1 -1
  42. data/lib/berkshelf/installer.rb +115 -104
  43. data/lib/berkshelf/location.rb +22 -121
  44. data/lib/berkshelf/locations/base.rb +75 -0
  45. data/lib/berkshelf/locations/git.rb +196 -0
  46. data/lib/berkshelf/locations/github.rb +8 -0
  47. data/lib/berkshelf/locations/path.rb +78 -0
  48. data/lib/berkshelf/lockfile.rb +452 -290
  49. data/lib/berkshelf/logger.rb +9 -3
  50. data/lib/berkshelf/mixin/logging.rb +4 -9
  51. data/lib/berkshelf/resolver.rb +12 -12
  52. data/lib/berkshelf/source.rb +13 -1
  53. data/lib/berkshelf/version.rb +1 -1
  54. data/spec/fixtures/cookbooks/example_cookbook-0.5.0/metadata.rb +3 -7
  55. data/spec/fixtures/cookbooks/example_cookbook/metadata.rb +3 -6
  56. data/spec/spec_helper.rb +5 -6
  57. data/spec/support/matchers/file_system_matchers.rb +4 -0
  58. data/spec/support/shared_examples/formatter.rb +11 -0
  59. data/spec/unit/berkshelf/berksfile_spec.rb +25 -28
  60. data/spec/unit/berkshelf/cli_spec.rb +19 -11
  61. data/spec/unit/berkshelf/dependency_spec.rb +4 -164
  62. data/spec/unit/berkshelf/formatters/base_spec.rb +35 -0
  63. data/spec/unit/berkshelf/formatters/human_spec.rb +7 -0
  64. data/spec/unit/berkshelf/formatters/json_spec.rb +7 -0
  65. data/spec/unit/berkshelf/formatters/null_spec.rb +7 -11
  66. data/spec/unit/berkshelf/location_spec.rb +16 -144
  67. data/spec/unit/berkshelf/locations/base_spec.rb +80 -0
  68. data/spec/unit/berkshelf/locations/git_spec.rb +249 -0
  69. data/spec/unit/berkshelf/locations/path_spec.rb +107 -0
  70. data/spec/unit/berkshelf/lockfile_parser_spec.rb +3 -3
  71. data/spec/unit/berkshelf/lockfile_spec.rb +55 -11
  72. data/spec/unit/berkshelf/logger_spec.rb +2 -2
  73. data/spec/unit/berkshelf/mixin/logging_spec.rb +5 -9
  74. data/spec/unit/berkshelf/source_spec.rb +32 -13
  75. data/spec/unit/berkshelf_spec.rb +6 -9
  76. metadata +33 -33
  77. data/.ruby-version +0 -1
  78. data/berkshelf-complete.sh +0 -75
  79. data/lib/berkshelf/formatters.rb +0 -110
  80. data/lib/berkshelf/formatters/human_readable.rb +0 -142
  81. data/lib/berkshelf/git.rb +0 -204
  82. data/lib/berkshelf/locations/git_location.rb +0 -135
  83. data/lib/berkshelf/locations/github_location.rb +0 -55
  84. data/lib/berkshelf/locations/mercurial_location.rb +0 -114
  85. data/lib/berkshelf/locations/path_location.rb +0 -88
  86. data/lib/berkshelf/mercurial.rb +0 -146
  87. data/lib/berkshelf/mixin.rb +0 -7
  88. data/spec/support/mercurial.rb +0 -123
  89. data/spec/unit/berkshelf/formatters_spec.rb +0 -114
  90. data/spec/unit/berkshelf/git_spec.rb +0 -312
  91. data/spec/unit/berkshelf/locations/git_location_spec.rb +0 -126
  92. data/spec/unit/berkshelf/locations/mercurial_location_spec.rb +0 -131
  93. data/spec/unit/berkshelf/locations/path_location_spec.rb +0 -25
  94. data/spec/unit/berkshelf/mercurial_spec.rb +0 -172
@@ -0,0 +1,42 @@
1
+ module Berkshelf
2
+ class BaseFormatter
3
+ class << self
4
+ #
5
+ # @macro formatter_method
6
+ # @method $1(*args)
7
+ # Create a formatter method for the declaration
8
+ #
9
+ def formatter_method(name)
10
+ class_eval <<-EOH, __FILE__, __LINE__ + 1
11
+ def #{name}(*args)
12
+ raise AbstractFunction,
13
+ "##{name} must be implemented on \#{self.class.name}!"
14
+ end
15
+ EOH
16
+ end
17
+ end
18
+
19
+ # UI methods
20
+ formatter_method :deprecation
21
+ formatter_method :error
22
+ formatter_method :msg
23
+ formatter_method :warn
24
+
25
+ # Object methods
26
+ formatter_method :fetch
27
+ formatter_method :install
28
+ formatter_method :list
29
+ formatter_method :outdated
30
+ formatter_method :package
31
+ formatter_method :search
32
+ formatter_method :show
33
+ formatter_method :skip
34
+ formatter_method :upload
35
+ formatter_method :use
36
+ formatter_method :vendor
37
+ formatter_method :version
38
+
39
+ # The cleanup hook is defined by subclasses and is called by the CLI.
40
+ def cleanup_hook; end
41
+ end
42
+ end
@@ -0,0 +1,145 @@
1
+ module Berkshelf
2
+ class HumanFormatter < BaseFormatter
3
+ # Output the version of Berkshelf
4
+ def version
5
+ Berkshelf.ui.info Berkshelf::VERSION
6
+ end
7
+
8
+ # @param [Berkshelf::Dependency] dependency
9
+ def fetch(dependency)
10
+ Berkshelf.ui.info "Fetching '#{dependency.name}' from #{dependency.location}"
11
+ end
12
+
13
+ # Output a Cookbook installation message using {Berkshelf.ui}
14
+ #
15
+ # @param [Source] source
16
+ # the source the dependency is being downloaded from
17
+ # @param [RemoteCookbook] cookbook
18
+ # the cookbook to be downloaded
19
+ def install(source, cookbook)
20
+ message = "Installing #{cookbook.name} (#{cookbook.version})"
21
+
22
+ unless source.default?
23
+ message << " from #{source}"
24
+ message << " ([#{cookbook.location_type}] #{cookbook.location_path})"
25
+ end
26
+
27
+ Berkshelf.ui.info(message)
28
+ end
29
+
30
+ # Output a Cookbook use message using {Berkshelf.ui}
31
+ #
32
+ # @param [Dependency] dependency
33
+ def use(dependency)
34
+ message = "Using #{dependency.name} (#{dependency.locked_version})"
35
+ message << " from #{dependency.location}" if dependency.location
36
+ Berkshelf.ui.info(message)
37
+ end
38
+
39
+ # Output a Cookbook upload message using {Berkshelf.ui}
40
+ #
41
+ # @param [Berkshelf::CachedCookbook] cookbook
42
+ # @param [Ridley::Connection] conn
43
+ def upload(cookbook, conn)
44
+ Berkshelf.ui.info "Uploading #{cookbook.cookbook_name} (#{cookbook.version}) to: '#{conn.server_url}'"
45
+ end
46
+
47
+ # Output a Cookbook skip message using {Berkshelf.ui}
48
+ #
49
+ # @param [Berkshelf::CachedCookbook] cookbook
50
+ # @param [Ridley::Connection] conn
51
+ def skip(cookbook, conn)
52
+ Berkshelf.ui.info "Skipping #{cookbook.cookbook_name} (#{cookbook.version}) (frozen)"
53
+ end
54
+
55
+ # Output a list of outdated cookbooks and the most recent version
56
+ # using {Berkshelf.ui}
57
+ #
58
+ # @param [Hash] hash
59
+ # the list of outdated cookbooks in the format
60
+ # { 'cookbook' => { 'api.berkshelf.com' => #<Cookbook> } }
61
+ def outdated(hash)
62
+ hash.keys.each do |name|
63
+ hash[name].each do |source, newest|
64
+ string = " * #{newest.name} (#{newest.version})"
65
+ unless source == Berksfile::DEFAULT_API_URL
66
+ string << " [#{source}]"
67
+ end
68
+ Berkshelf.ui.info string
69
+ end
70
+ end
71
+ end
72
+
73
+ # Output a Cookbook package message using {Berkshelf.ui}
74
+ #
75
+ # @param [String] destination
76
+ def package(destination)
77
+ Berkshelf.ui.info "Cookbook(s) packaged to #{destination}"
78
+ end
79
+
80
+ # Output a list of cookbooks using {Berkshelf.ui}
81
+ #
82
+ # @param [Array<Dependency>] list
83
+ def list(dependencies)
84
+ Berkshelf.ui.info "Cookbooks installed by your Berksfile:"
85
+ dependencies.each do |dependency|
86
+ out = " * #{dependency}"
87
+ out << " from #{dependency.location}" if dependency.location
88
+ Berkshelf.ui.info(out)
89
+ end
90
+ end
91
+
92
+ # Ouput Cookbook search results using {Berkshelf.ui}
93
+ #
94
+ # @param [Array<APIClient::RemoteCookbook>] results
95
+ def search(results)
96
+ results.sort_by(&:name).each do |remote_cookbook|
97
+ Berkshelf.ui.info "#{remote_cookbook.name} (#{remote_cookbook.version})"
98
+ end
99
+ end
100
+
101
+ # Output Cookbook info message using {Berkshelf.ui}
102
+ #
103
+ # @param [CachedCookbook] cookbook
104
+ def show(cookbook)
105
+ Berkshelf.ui.info(cookbook.pretty_print)
106
+ end
107
+
108
+ # Output Cookbook vendor info message using {Berkshelf.ui}
109
+ #
110
+ # @param [CachedCookbook] cookbook
111
+ # @param [String] destination
112
+ def vendor(cookbook, destination)
113
+ cookbook_destination = File.join(destination, cookbook.cookbook_name)
114
+ Berkshelf.ui.info "Vendoring #{cookbook.cookbook_name} (#{cookbook.version}) to #{cookbook_destination}"
115
+ end
116
+
117
+ # Output a generic message using {Berkshelf.ui}
118
+ #
119
+ # @param [String] message
120
+ def msg(message)
121
+ Berkshelf.ui.info message
122
+ end
123
+
124
+ # Output an error message using {Berkshelf.ui}
125
+ #
126
+ # @param [String] message
127
+ def error(message)
128
+ Berkshelf.ui.error message
129
+ end
130
+
131
+ # Output a warning message using {Berkshelf.ui}
132
+ #
133
+ # @param [String] message
134
+ def warn(message)
135
+ Berkshelf.ui.warn message
136
+ end
137
+
138
+ # Output a deprecation warning
139
+ #
140
+ # @param [String] message
141
+ def deprecation(message)
142
+ Berkshelf.ui.info "DEPRECATED: #{message}"
143
+ end
144
+ end
145
+ end
@@ -1,164 +1,180 @@
1
1
  module Berkshelf
2
- module Formatters
3
- class JSON
4
- include AbstractFormatter
5
-
6
- register_formatter :json
2
+ class JsonFormatter < BaseFormatter
3
+ # Output the version of Berkshelf
4
+ def version
5
+ @output = { version: Berkshelf::VERSION }
6
+ end
7
7
 
8
- # Output the version of Berkshelf
9
- def version
10
- @output = { version: Berkshelf::VERSION }
11
- end
8
+ def initialize
9
+ @output = {
10
+ cookbooks: [],
11
+ errors: [],
12
+ messages: [],
13
+ warnings: [],
14
+ }
15
+ @cookbooks = Hash.new
12
16
 
13
- def initialize
14
- @output = {
15
- cookbooks: Array.new,
16
- errors: Array.new,
17
- messages: Array.new
18
- }
19
- @cookbooks = Hash.new
17
+ Berkshelf.ui.mute { super }
18
+ end
20
19
 
21
- Berkshelf.ui.mute { super }
20
+ def cleanup_hook
21
+ cookbooks.each do |name, details|
22
+ details[:name] = name
23
+ output[:cookbooks] << details
22
24
  end
23
25
 
24
- def cleanup_hook
25
- cookbooks.each do |name, details|
26
- details[:name] = name
27
- output[:cookbooks] << details
28
- end
29
-
30
- puts ::JSON.pretty_generate(output)
31
- end
26
+ puts ::JSON.pretty_generate(output)
27
+ end
32
28
 
33
- # @param [Berkshelf::Dependency] dependency
34
- def fetch(dependency)
35
- cookbooks[dependency] ||= {}
36
- cookbooks[dependency][:version] = dependency.locked_version.to_s
37
- cookbooks[dependency][:location] = dependency.location
38
- end
29
+ # @param [Berkshelf::Dependency] dependency
30
+ def fetch(dependency)
31
+ cookbooks[dependency] ||= {}
32
+ cookbooks[dependency][:version] = dependency.locked_version.to_s
33
+ cookbooks[dependency][:location] = dependency.location
34
+ end
39
35
 
40
- # Add a Cookbook installation entry to delayed output
41
- #
42
- # @param [Source] source
43
- # the source the dependency is being downloaded from
44
- # @param [RemoteCookbook] cookbook
45
- # the cookbook to be downloaded
46
- def install(source, cookbook)
47
- cookbooks[cookbook.name] ||= {}
48
- cookbooks[cookbook.name][:version] = cookbook.version
49
-
50
- unless source.default?
51
- cookbooks[cookbook.name][:api_source] = source.uri
52
- cookbooks[cookbook.name][:location_path] = cookbook.location_path
53
- end
36
+ # Add a Cookbook installation entry to delayed output
37
+ #
38
+ # @param [Source] source
39
+ # the source the dependency is being downloaded from
40
+ # @param [RemoteCookbook] cookbook
41
+ # the cookbook to be downloaded
42
+ def install(source, cookbook)
43
+ cookbooks[cookbook.name] ||= {}
44
+ cookbooks[cookbook.name][:version] = cookbook.version
45
+
46
+ unless source.default?
47
+ cookbooks[cookbook.name][:api_source] = source.uri
48
+ cookbooks[cookbook.name][:location_path] = cookbook.location_path
54
49
  end
50
+ end
55
51
 
56
- # Add a Cookbook use entry to delayed output
57
- #
58
- # @param [Dependency] dependency
59
- def use(dependency)
60
- cookbooks[dependency.name] ||= {}
61
- cookbooks[dependency.name][:version] = dependency.cached_cookbook.version
52
+ # Add a Cookbook use entry to delayed output
53
+ #
54
+ # @param [Dependency] dependency
55
+ def use(dependency)
56
+ cookbooks[dependency.name] ||= {}
57
+ cookbooks[dependency.name][:version] = dependency.cached_cookbook.version
62
58
 
63
- if dependency.location.is_a?(PathLocation)
64
- cookbooks[dependency.name][:metadata] = true if dependency.location.metadata?
65
- cookbooks[dependency.name][:location] = dependency.location.relative_path
66
- end
59
+ if dependency.location.is_a?(PathLocation)
60
+ cookbooks[dependency.name][:metadata] = true if dependency.location.metadata?
61
+ cookbooks[dependency.name][:location] = dependency.location.relative_path
67
62
  end
63
+ end
68
64
 
69
- # Add a Cookbook upload entry to delayed output
70
- #
71
- # @param [Berkshelf::CachedCookbook] cookbook
72
- # @param [Ridley::Connection] conn
73
- def upload(cookbook, conn)
74
- name = cookbook.cookbook_name
75
- cookbooks[name] ||= {}
76
- cookbooks[name][:version] = cookbook.version
77
- cookbooks[name][:uploaded_to] = conn.server_url
78
- end
65
+ # Add a Cookbook upload entry to delayed output
66
+ #
67
+ # @param [Berkshelf::CachedCookbook] cookbook
68
+ # @param [Ridley::Connection] conn
69
+ def upload(cookbook, conn)
70
+ name = cookbook.cookbook_name
71
+ cookbooks[name] ||= {}
72
+ cookbooks[name][:version] = cookbook.version
73
+ cookbooks[name][:uploaded_to] = conn.server_url
74
+ end
79
75
 
80
- # Add a Cookbook skip entry to delayed output
81
- #
82
- # @param [Berkshelf::CachedCookbook] cookbook
83
- # @param [Ridley::Connection] conn
84
- def skip(cookbook, conn)
85
- name = cookbook.cookbook_name
86
- cookbooks[name] ||= {}
87
- cookbooks[name][:version] = cookbook.version
88
- cookbooks[name][:skipped] = true
89
- end
76
+ # Add a Cookbook skip entry to delayed output
77
+ #
78
+ # @param [Berkshelf::CachedCookbook] cookbook
79
+ # @param [Ridley::Connection] conn
80
+ def skip(cookbook, conn)
81
+ name = cookbook.cookbook_name
82
+ cookbooks[name] ||= {}
83
+ cookbooks[name][:version] = cookbook.version
84
+ cookbooks[name][:skipped] = true
85
+ end
90
86
 
91
- # Output a list of outdated cookbooks and the most recent version
92
- # to delayed output
93
- #
94
- # @param [Hash] hash
95
- # the list of outdated cookbooks in the format
96
- # { 'cookbook' => { 'api.berkshelf.com' => #<Cookbook> } }
97
- def outdated(hash)
98
- hash.keys.each do |name|
99
- hash[name].each do |source, cookbook|
100
- cookbooks[name] ||= {}
101
- cookbooks[name][:version] = cookbook.version
102
- cookbooks[name][:sources] ||= {}
103
- cookbooks[name][:sources][source] = cookbook
104
- end
87
+ # Output a list of outdated cookbooks and the most recent version
88
+ # to delayed output
89
+ #
90
+ # @param [Hash] hash
91
+ # the list of outdated cookbooks in the format
92
+ # { 'cookbook' => { 'api.berkshelf.com' => #<Cookbook> } }
93
+ def outdated(hash)
94
+ hash.keys.each do |name|
95
+ hash[name].each do |source, cookbook|
96
+ cookbooks[name] ||= {}
97
+ cookbooks[name][:version] = cookbook.version
98
+ cookbooks[name][:sources] ||= {}
99
+ cookbooks[name][:sources][source] = cookbook
105
100
  end
106
101
  end
102
+ end
107
103
 
108
- # Output a list of cookbooks to delayed output
109
- #
110
- # @param [Array<Dependency>] dependencies
111
- def list(dependencies)
112
- dependencies.each do |dependency, cookbook|
113
- cookbooks[dependency.name] ||= {}
114
- cookbooks[dependency.name][:version] = dependency.locked_version.to_s
115
- if dependency.location
116
- cookbooks[dependency.name][:location] = dependency.location
117
- end
104
+ # Output a package message using
105
+ #
106
+ # @param [String] destination
107
+ def package(destination)
108
+ output[:messages] << "Cookbook(s) packaged to #{destination}"
109
+ end
110
+
111
+ # Output a list of cookbooks to delayed output
112
+ #
113
+ # @param [Array<Dependency>] dependencies
114
+ def list(dependencies)
115
+ dependencies.each do |dependency, cookbook|
116
+ cookbooks[dependency.name] ||= {}
117
+ cookbooks[dependency.name][:version] = dependency.locked_version.to_s
118
+ if dependency.location
119
+ cookbooks[dependency.name][:location] = dependency.location
118
120
  end
119
121
  end
122
+ end
120
123
 
121
- # Output Cookbook info entry to delayed output
122
- #
123
- # @param [CachedCookbook] cookbook
124
- def show(cookbook)
125
- cookbooks[cookbook.cookbook_name] = cookbook.pretty_hash
126
- end
124
+ # Output Cookbook info entry to delayed output
125
+ #
126
+ # @param [CachedCookbook] cookbook
127
+ def show(cookbook)
128
+ cookbooks[cookbook.cookbook_name] = cookbook.pretty_hash
129
+ end
127
130
 
128
- # Add a vendor message to delayed output
129
- #
130
- # @param [CachedCookbook] cookbook
131
- # @param [String] destination
132
- def vendor(cookbook, destination)
133
- cookbook_destination = File.join(destination, cookbook.cookbook_name)
134
- msg("Vendoring #{cookbook.cookbook_name} (#{cookbook.version}) to #{cookbook_destination}")
131
+ # Ouput Cookbook search results to delayed output
132
+ #
133
+ # @param [Array<APIClient::RemoteCookbook>] results
134
+ def search(results)
135
+ results.sort_by(&:name).each do |remote_cookbook|
136
+ cookbooks[remote_cookbook.name] ||= {}
137
+ cookbooks[remote_cookbook.name][:version] = remote_cookbook.version
135
138
  end
139
+ end
136
140
 
137
- # Add a generic message entry to delayed output
138
- #
139
- # @param [String] message
140
- def msg(message)
141
- output[:messages] << message
142
- end
141
+ # Add a vendor message to delayed output
142
+ #
143
+ # @param [CachedCookbook] cookbook
144
+ # @param [String] destination
145
+ def vendor(cookbook, destination)
146
+ cookbook_destination = File.join(destination, cookbook.cookbook_name)
147
+ msg("Vendoring #{cookbook.cookbook_name} (#{cookbook.version}) to #{cookbook_destination}")
148
+ end
143
149
 
144
- # Add an error message entry to delayed output
145
- #
146
- # @param [String] message
147
- def error(message)
148
- output[:errors] << message
149
- end
150
+ # Add a generic message entry to delayed output
151
+ #
152
+ # @param [String] message
153
+ def msg(message)
154
+ output[:messages] << message
155
+ end
150
156
 
151
- # Add a warning message entry to delayed output
152
- #
153
- # @param [String] message
154
- def warn(message)
155
- output[:warnings] << message
156
- end
157
+ # Add an error message entry to delayed output
158
+ #
159
+ # @param [String] message
160
+ def error(message)
161
+ output[:errors] << message
162
+ end
157
163
 
158
- private
164
+ # Add a warning message entry to delayed output
165
+ #
166
+ # @param [String] message
167
+ def warn(message)
168
+ output[:warnings] << message
169
+ end
159
170
 
160
- attr_reader :output
161
- attr_reader :cookbooks
171
+ def deprecation(message)
172
+ output[:warnings] << "DEPRECATED: #{message}"
162
173
  end
174
+
175
+ private
176
+
177
+ attr_reader :output
178
+ attr_reader :cookbooks
163
179
  end
164
180
  end