berkshelf 3.0.0.beta7 → 3.0.0.beta8

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.
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
@@ -14,11 +14,7 @@ module Berkshelf
14
14
  class DeprecatedError < BerkshelfError; status_code(10); end
15
15
  class InternalError < BerkshelfError; status_code(99); end
16
16
  class ArgumentError < InternalError; end
17
- class AbstractFunction < InternalError
18
- def to_s
19
- 'Function must be implemented on includer'
20
- end
21
- end
17
+ class AbstractFunction < InternalError; end
22
18
 
23
19
  class BerksfileNotFound < BerkshelfError
24
20
  status_code(100)
@@ -34,75 +30,45 @@ module Berkshelf
34
30
  end
35
31
  end
36
32
 
37
- class NoVersionForConstraints < BerkshelfError; status_code(101); end
38
- class DuplicateLocationDefined < BerkshelfError; status_code(102); end
39
- class CookbookNotFound < BerkshelfError; status_code(103); end
40
-
41
- class GitError < BerkshelfError
42
- status_code(104)
33
+ class CookbookNotFound < BerkshelfError
34
+ status_code(103)
43
35
 
44
- # @param [#to_s] stderr
45
- # the error that came from stderr
46
- def initialize(stderr)
47
- @stderr = stderr.to_s
48
- end
49
-
50
- # A common header for all git errors. The #to_s method should
51
- # use this before outputting any specific errors.
52
- #
53
- # @return [String]
54
- def header
55
- 'An error occurred during Git execution:'
36
+ def initialize(name, version, location)
37
+ @name = name
38
+ @version = version
39
+ @location = location
56
40
  end
57
41
 
58
42
  def to_s
59
- [
60
- header,
61
- "",
62
- " " + @stderr.to_s.split("\n").map(&:strip).join("\n "),
63
- ""
64
- ].join("\n")
43
+ if @version
44
+ "Cookbook '#{@name}' (#{@version}) not found #{@location}!"
45
+ else
46
+ "Cookbook '#{@name}' not found #{@location}!"
47
+ end
65
48
  end
66
49
  end
67
50
 
68
- class AmbiguousGitRef < GitError
69
- def initialize(ref)
70
- @ref = ref
71
- end
72
-
73
- def to_s
74
- [
75
- header,
76
- "",
77
- " Ambiguous Git ref: '#{@ref}'",
78
- "",
79
- ].join("\n")
80
- end
81
- end
51
+ class DuplicateDependencyDefined < BerkshelfError
52
+ status_code(105)
82
53
 
83
- class InvalidGitRef < GitError
84
- def initialize(ref)
85
- @ref = ref
54
+ def initialize(name)
55
+ @name = name
86
56
  end
87
57
 
88
58
  def to_s
89
- [
90
- header,
91
- "",
92
- " Invalid Git ref: '#{@ref}'",
93
- "",
94
- ].join("\n")
59
+ out = "Your Berksfile contains multiple entries named "
60
+ out << "'#{@name}'. Please remove duplicate dependencies, or put them in "
61
+ out << "different groups."
62
+ out
95
63
  end
96
64
  end
97
65
 
98
- class DuplicateDependencyDefined < BerkshelfError; status_code(105); end
99
-
100
66
  class NoSolutionError < BerkshelfError
101
67
  status_code(106)
102
68
 
103
69
  attr_reader :demands
104
70
 
105
- # @param [Array<Berkshelf::Dependency>] demands
71
+ # @param [Array<Dependency>] demands
106
72
  def initialize(demands)
107
73
  @demands = demands
108
74
  end
@@ -113,79 +79,6 @@ module Berkshelf
113
79
  end
114
80
 
115
81
  class CookbookSyntaxError < BerkshelfError; status_code(107); end
116
-
117
- class MercurialError < BerkshelfError
118
- status_code(108);
119
- end
120
-
121
- class InvalidHgURI < BerkshelfError
122
- status_code(110)
123
-
124
- # @param [String] uri
125
- def initialize(uri)
126
- @uri = uri
127
- end
128
-
129
- def to_s
130
- "'#{@uri}' is not a valid Mercurial URI"
131
- end
132
- end
133
-
134
- class InvalidGitURI < BerkshelfError
135
- status_code(110)
136
-
137
- # @param [String] uri
138
- def initialize(uri)
139
- @uri = uri
140
- end
141
-
142
- def to_s
143
- "'#{@uri}' is not a valid Git URI"
144
- end
145
- end
146
-
147
- class InvalidGitHubIdentifier < BerkshelfError
148
- status_code(110)
149
-
150
- # @param [String] repo_identifier
151
- def initialize(repo_identifier)
152
- @repo_identifier = repo_identifier
153
- end
154
-
155
- def to_s
156
- "'#{@repo_identifier}' is not a valid GitHub identifier - should not end in '.git'"
157
- end
158
- end
159
-
160
- class UnknownGitHubProtocol < BerkshelfError
161
- status_code(110)
162
-
163
- # @param [String] protocol
164
- def initialize(protocol)
165
- @protocol = protocol
166
- end
167
-
168
- def to_s
169
- "'#{@protocol}' is not supported for the 'github' location key - please use 'git' instead"
170
- end
171
- end
172
-
173
- class MercurialNotFound < BerkshelfError
174
- status_code(111)
175
-
176
- def to_s
177
- 'Could not find a Mercurial executable in your path - please add it and try again'
178
- end
179
- end
180
-
181
- class GitNotFound < BerkshelfError
182
- status_code(110)
183
-
184
- def to_s
185
- 'Could not find a Git executable in your path - please add it and try again'
186
- end
187
- end
188
-
189
82
  class ConstraintNotSatisfied < BerkshelfError; status_code(111); end
190
83
  class BerksfileReadError < BerkshelfError
191
84
  status_code(113)
@@ -197,7 +90,6 @@ module Berkshelf
197
90
  @error_backtrace = original_error.backtrace
198
91
  end
199
92
 
200
-
201
93
  def status_code
202
94
  @original_error.respond_to?(:status_code) ? @original_error.status_code : 113
203
95
  end
@@ -219,9 +111,9 @@ module Berkshelf
219
111
  class MismatchedCookbookName < BerkshelfError
220
112
  status_code(114)
221
113
 
222
- # @param [Berkshelf::Dependency] dependency
114
+ # @param [Dependency] dependency
223
115
  # the dependency with the expected name
224
- # @param [Berkshelf::CachedCookbook] cached_cookbook
116
+ # @param [CachedCookbook] cached_cookbook
225
117
  # the cached_cookbook with the mismatched name
226
118
  def initialize(dependency, cached_cookbook)
227
119
  @dependency = dependency
@@ -229,17 +121,18 @@ module Berkshelf
229
121
  end
230
122
 
231
123
  def to_s
232
- [
233
- "In your Berksfile, you have:",
234
- "",
235
- " cookbook '#{@dependency.name}'",
236
- "",
237
- "But that cookbook is actually named '#{@cached_cookbook.cookbook_name}'",
238
- "",
239
- "This can cause potentially unwanted side-effects in the future",
240
- "",
241
- "NOTE: If you don't explicitly set the `name` attribute in the metadata, the name of the directory will be used!",
242
- ].join("\n")
124
+ out = "In your Berksfile, you have:\n"
125
+ out << "\n"
126
+ out << " cookbook '#{@dependency.name}'\n"
127
+ out << "\n"
128
+ out << "But that cookbook is actually named '#{@cached_cookbook.cookbook_name}'\n"
129
+ out << "\n"
130
+ out << "This can cause potentially unwanted side-effects in the future.\n"
131
+ out << "\n"
132
+ out << "NOTE: If you do not explicitly set the 'name' attribute in the "
133
+ out << "metadata, the name of the directory will be used instead. This "
134
+ out << "is often a cause of confusion for dependency solving."
135
+ out
243
136
  end
244
137
  end
245
138
 
@@ -251,51 +144,79 @@ module Berkshelf
251
144
  end
252
145
 
253
146
  def to_s
254
- [
255
- 'Invalid configuration:',
256
- @errors.map { |key, errors| errors.map { |error| " #{key} #{error}" } },
257
- ].join("\n")
147
+ out = "Invalid configuration:\n"
148
+ @errors.each do |key, errors|
149
+ errors.each do |error|
150
+ out << " #{key} #{error}\n"
151
+ end
152
+ end
153
+
154
+ out.strip
258
155
  end
259
156
  end
260
157
 
261
- class ConfigExists < BerkshelfError; status_code(116); end
262
- class ConfigurationError < BerkshelfError; status_code(117); end
263
- class InsufficientPrivledges < BerkshelfError; status_code(119); end
158
+ class InsufficientPrivledges < BerkshelfError
159
+ status_code(119)
160
+
161
+ def initialize(path)
162
+ @path = path
163
+ end
164
+
165
+ def to_s
166
+ "You do not have permission to write to '#{@path}'! Please chown the " \
167
+ "path to the current user, chmod the permissions to include the " \
168
+ "user, or choose a different path."
169
+ end
170
+ end
264
171
 
265
172
  class DependencyNotFound < BerkshelfError
266
173
  status_code(120)
267
174
 
268
- # @param [String, Array<String>] cookbooks
269
- # the list of cookbooks that were not defined
270
- def initialize(cookbooks)
271
- @cookbooks = Array(cookbooks)
175
+ # @param [String, Array<String>] names
176
+ # the list of cookbook names that were not defined
177
+ def initialize(names)
178
+ @names = Array(names)
272
179
  end
273
180
 
274
181
  def to_s
275
- list = @cookbooks.collect { |cookbook| "'#{cookbook}'" }.join(', ')
276
-
277
- if @cookbooks.size == 1
278
- "Could not find cookbook #{list}. Make sure it is in your " \
279
- "Berksfile, then run `berks install` to download and install the " \
280
- "missing dependencies."
182
+ if @names.size == 1
183
+ "Dependency '#{@names.first}' was not found. Please make sure it is " \
184
+ "in your Berksfile, and then run `berks install` to download and " \
185
+ "install the missing dependencies."
281
186
  else
282
- "Could not find cookbooks #{list}. Make sure they are in your " \
283
- "Berksfile, then run `berks install` to download and install the " \
284
- "missing dependencies."
187
+ out = "The following dependencies were not found:\n"
188
+ @names.each do |name|
189
+ out << " * #{name}\n"
190
+ end
191
+ out << "\n"
192
+ out << "Please make sure they are in your Berksfile, and then run "
193
+ out << "`berks install` to download and install the missing "
194
+ out << "dependencies."
195
+ out
285
196
  end
286
197
  end
287
198
  end
288
199
 
289
- class ValidationFailed < BerkshelfError; status_code(121); end
290
- class InvalidVersionConstraint < BerkshelfError; status_code(122); end
291
- class CommunitySiteError < BerkshelfError; status_code(123); end
200
+ class CommunitySiteError < BerkshelfError
201
+ status_code(123)
202
+
203
+ def initialize(uri, message)
204
+ @uri = uri
205
+ @message = message
206
+ end
207
+
208
+ def to_s
209
+ "An unexpected error occurred retrieving #{@message} from the cookbook " \
210
+ "site at '#{@api_uri}'."
211
+ end
212
+ end
292
213
 
293
214
  class CookbookValidationFailure < BerkshelfError
294
215
  status_code(124)
295
216
 
296
- # @param [Berkshelf::Location] location
217
+ # @param [Location] location
297
218
  # the location (or any subclass) raising this validation error
298
- # @param [Berkshelf::CachedCookbook] cached_cookbook
219
+ # @param [CachedCookbook] cached_cookbook
299
220
  # the cached_cookbook that does not satisfy the constraint
300
221
  def initialize(dependency, cached_cookbook)
301
222
  @dependency = dependency
@@ -307,10 +228,7 @@ module Berkshelf
307
228
  end
308
229
  end
309
230
 
310
- class ClientKeyFileNotFound < BerkshelfError; status_code(125); end
311
-
312
231
  class UploadFailure < BerkshelfError; end
313
-
314
232
  class FrozenCookbook < UploadFailure
315
233
  status_code(126)
316
234
 
@@ -320,18 +238,18 @@ module Berkshelf
320
238
  end
321
239
 
322
240
  def to_s
323
- "The cookbook #{@cookbook.cookbook_name} (#{@cookbook.version})" <<
324
- " already exists and is frozen on the Chef Server. Use the --force" <<
325
- " option to override."
241
+ "The cookbook #{@cookbook.cookbook_name} (#{@cookbook.version}) " \
242
+ "already exists and is frozen on the Chef Server. Use the --force " \
243
+ "option to override."
326
244
  end
327
245
  end
328
246
 
329
247
  class OutdatedDependency < BerkshelfError
330
248
  status_code(128)
331
249
 
332
- # @param [Berkshelf::Dependency] locked_dependency
250
+ # @param [Dependency] locked_dependency
333
251
  # the locked dependency
334
- # @param [Berkshelf::Dependency] dependency
252
+ # @param [Dependency] dependency
335
253
  # the dependency that is outdated
336
254
  def initialize(locked, dependency)
337
255
  @locked = locked
@@ -384,7 +302,7 @@ module Berkshelf
384
302
  # Raised when a cookbook or its recipes contain a space or invalid
385
303
  # character in the path.
386
304
  #
387
- # @param [Berkshelf::CachedCookbook] cookbook
305
+ # @param [CachedCookbook] cookbook
388
306
  # the cookbook that failed validation
389
307
  # @param [Array<#to_s>] files
390
308
  # the list of files that were not valid
@@ -407,25 +325,6 @@ module Berkshelf
407
325
  end
408
326
  end
409
327
 
410
- # Raised when a CachedCookbook has a license file that isn't allowed
411
- # by the Berksfile.
412
- #
413
- # @param [Berkshelf::CachedCookbook] cookbook
414
- # the cookbook that failed license validation
415
- class LicenseNotAllowed < BerkshelfError
416
- status_code(133)
417
-
418
- def initialize(cookbook)
419
- @cookbook = cookbook
420
- end
421
-
422
- def to_s
423
- msg = "'#{@cookbook.cookbook_name}' has a license of '#{@cookbook.metadata.license}', but"
424
- msg << " '#{@cookbook.metadata.license}' is not in your list of allowed licenses"
425
- msg
426
- end
427
- end
428
-
429
328
  class LicenseNotFound < BerkshelfError
430
329
  status_code(134)
431
330
 
@@ -437,7 +336,7 @@ module Berkshelf
437
336
 
438
337
  def to_s
439
338
  "Unknown license: '#{license}'\n" +
440
- "Available licenses: #{Berkshelf::CookbookGenerator::LICENSES.join(', ')}"
339
+ "Available licenses: #{CookbookGenerator::LICENSES.join(', ')}"
441
340
  end
442
341
  end
443
342
 
@@ -480,16 +379,15 @@ module Berkshelf
480
379
  class InvalidSourceURI < BerkshelfError
481
380
  status_code(137)
482
381
 
483
- attr_reader :reason
484
-
485
382
  def initialize(url, reason = nil)
486
383
  @url = url
487
384
  @reason = reason
488
385
  end
489
386
 
490
387
  def to_s
491
- msg = "'#{@url}' is not a valid Berkshelf source URI."
492
- msg + " #{reason}." unless reason.nil?
388
+ msg = "'#{@url}' is not a valid Berkshelf source URI."
389
+ msg << " #{@reason}." unless @reason.nil?
390
+ msg
493
391
  end
494
392
  end
495
393
 
@@ -513,11 +411,11 @@ module Berkshelf
513
411
  end
514
412
 
515
413
  def to_s
516
- "#{@path} does not appear to be a valid cookbook. Does it have a `metadata.rb`?"
414
+ "The resource at '#{@path}' does not appear to be a valid cookbook. " \
415
+ "Does it have a metadata.rb?"
517
416
  end
518
417
  end
519
418
 
520
- class InvalidLockFile < BerkshelfError; status_code(142); end
521
419
  class PackageError < BerkshelfError; status_code(143); end
522
420
 
523
421
  class LockfileOutOfSync < BerkshelfError
@@ -532,25 +430,26 @@ module Berkshelf
532
430
  status_code(145)
533
431
 
534
432
  def initialize(dependency)
535
- name = dependency.name
536
- version = dependency.locked_version
433
+ @name = dependency.name
434
+ @version = dependency.locked_version
435
+ end
537
436
 
538
- super "The cookbook '#{name} (#{version})' is not installed. Please " \
539
- "run `berks install` to download and install the missing " \
540
- "dependency."
437
+ def to_s
438
+ "The cookbook '#{@name} (#{@version})' is not installed. Please run " \
439
+ "`berks install` to download and install the missing dependency."
541
440
  end
542
441
  end
543
442
 
544
443
  class NoAPISourcesDefined < BerkshelfError
545
444
  status_code(146)
546
445
 
547
- def initialize
548
- super "Your Berksfile does not define any API sources! You must define " \
549
- "at least one source in order to download cookbooks. To add the " \
550
- "default Berkshelf API server, add the following code to the top of " \
551
- "your Berksfile:" \
552
- "\n\n" \
553
- " source 'https://api.berkshelf.com'"
446
+ def to_s
447
+ "Your Berksfile does not define any API sources! You must define " \
448
+ "at least one source in order to download cookbooks. To add the " \
449
+ "default Berkshelf API server, add the following code to the top of " \
450
+ "your Berksfile:" \
451
+ "\n\n" \
452
+ " source 'https://api.berkshelf.com'"
554
453
  end
555
454
  end
556
455
  end