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.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/.travis.yml +4 -1
- data/CONTRIBUTING.md +1 -1
- data/Gemfile +0 -1
- data/Guardfile +0 -8
- data/README.md +33 -13
- data/berkshelf.gemspec +3 -3
- data/features/commands/install.feature +16 -88
- data/features/commands/search.feature +15 -0
- data/features/commands/shelf/show.feature +2 -2
- data/features/commands/shelf/uninstall.feature +1 -1
- data/features/commands/show.feature +3 -3
- data/features/commands/update.feature +29 -1
- data/features/commands/upload.feature +172 -7
- data/features/commands/vendor.feature +32 -0
- data/features/json_formatter.feature +26 -24
- data/features/lifecycle.feature +285 -0
- data/features/lockfile.feature +9 -7
- data/features/step_definitions/chef_server_steps.rb +1 -0
- data/features/step_definitions/cli_steps.rb +2 -2
- data/features/step_definitions/filesystem_steps.rb +2 -4
- data/gem_graph.png +0 -0
- data/generator_files/chefignore +0 -2
- data/lib/berkshelf.rb +39 -14
- data/lib/berkshelf/berksfile.rb +161 -113
- data/lib/berkshelf/cached_cookbook.rb +2 -2
- data/lib/berkshelf/cli.rb +15 -3
- data/lib/berkshelf/commands/shelf.rb +3 -7
- data/lib/berkshelf/community_rest.rb +9 -9
- data/lib/berkshelf/config.rb +3 -3
- data/lib/berkshelf/cookbook_generator.rb +0 -8
- data/lib/berkshelf/cookbook_store.rb +1 -2
- data/lib/berkshelf/dependency.rb +25 -138
- data/lib/berkshelf/downloader.rb +41 -7
- data/lib/berkshelf/errors.rb +113 -214
- data/lib/berkshelf/formatters/base.rb +42 -0
- data/lib/berkshelf/formatters/human.rb +145 -0
- data/lib/berkshelf/formatters/json.rb +149 -133
- data/lib/berkshelf/formatters/null.rb +8 -18
- data/lib/berkshelf/init_generator.rb +1 -1
- data/lib/berkshelf/installer.rb +115 -104
- data/lib/berkshelf/location.rb +22 -121
- data/lib/berkshelf/locations/base.rb +75 -0
- data/lib/berkshelf/locations/git.rb +196 -0
- data/lib/berkshelf/locations/github.rb +8 -0
- data/lib/berkshelf/locations/path.rb +78 -0
- data/lib/berkshelf/lockfile.rb +452 -290
- data/lib/berkshelf/logger.rb +9 -3
- data/lib/berkshelf/mixin/logging.rb +4 -9
- data/lib/berkshelf/resolver.rb +12 -12
- data/lib/berkshelf/source.rb +13 -1
- data/lib/berkshelf/version.rb +1 -1
- data/spec/fixtures/cookbooks/example_cookbook-0.5.0/metadata.rb +3 -7
- data/spec/fixtures/cookbooks/example_cookbook/metadata.rb +3 -6
- data/spec/spec_helper.rb +5 -6
- data/spec/support/matchers/file_system_matchers.rb +4 -0
- data/spec/support/shared_examples/formatter.rb +11 -0
- data/spec/unit/berkshelf/berksfile_spec.rb +25 -28
- data/spec/unit/berkshelf/cli_spec.rb +19 -11
- data/spec/unit/berkshelf/dependency_spec.rb +4 -164
- data/spec/unit/berkshelf/formatters/base_spec.rb +35 -0
- data/spec/unit/berkshelf/formatters/human_spec.rb +7 -0
- data/spec/unit/berkshelf/formatters/json_spec.rb +7 -0
- data/spec/unit/berkshelf/formatters/null_spec.rb +7 -11
- data/spec/unit/berkshelf/location_spec.rb +16 -144
- data/spec/unit/berkshelf/locations/base_spec.rb +80 -0
- data/spec/unit/berkshelf/locations/git_spec.rb +249 -0
- data/spec/unit/berkshelf/locations/path_spec.rb +107 -0
- data/spec/unit/berkshelf/lockfile_parser_spec.rb +3 -3
- data/spec/unit/berkshelf/lockfile_spec.rb +55 -11
- data/spec/unit/berkshelf/logger_spec.rb +2 -2
- data/spec/unit/berkshelf/mixin/logging_spec.rb +5 -9
- data/spec/unit/berkshelf/source_spec.rb +32 -13
- data/spec/unit/berkshelf_spec.rb +6 -9
- metadata +33 -33
- data/.ruby-version +0 -1
- data/berkshelf-complete.sh +0 -75
- data/lib/berkshelf/formatters.rb +0 -110
- data/lib/berkshelf/formatters/human_readable.rb +0 -142
- data/lib/berkshelf/git.rb +0 -204
- data/lib/berkshelf/locations/git_location.rb +0 -135
- data/lib/berkshelf/locations/github_location.rb +0 -55
- data/lib/berkshelf/locations/mercurial_location.rb +0 -114
- data/lib/berkshelf/locations/path_location.rb +0 -88
- data/lib/berkshelf/mercurial.rb +0 -146
- data/lib/berkshelf/mixin.rb +0 -7
- data/spec/support/mercurial.rb +0 -123
- data/spec/unit/berkshelf/formatters_spec.rb +0 -114
- data/spec/unit/berkshelf/git_spec.rb +0 -312
- data/spec/unit/berkshelf/locations/git_location_spec.rb +0 -126
- data/spec/unit/berkshelf/locations/mercurial_location_spec.rb +0 -131
- data/spec/unit/berkshelf/locations/path_location_spec.rb +0 -25
- data/spec/unit/berkshelf/mercurial_spec.rb +0 -172
data/lib/berkshelf/errors.rb
CHANGED
@@ -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
|
38
|
-
|
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
|
-
|
45
|
-
|
46
|
-
|
47
|
-
@
|
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
|
-
|
61
|
-
|
62
|
-
"
|
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
|
69
|
-
|
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
|
-
|
84
|
-
|
85
|
-
@ref = ref
|
54
|
+
def initialize(name)
|
55
|
+
@name = name
|
86
56
|
end
|
87
57
|
|
88
58
|
def to_s
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
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<
|
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 [
|
114
|
+
# @param [Dependency] dependency
|
223
115
|
# the dependency with the expected name
|
224
|
-
# @param [
|
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
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
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
|
-
|
256
|
-
|
257
|
-
|
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
|
262
|
-
|
263
|
-
|
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>]
|
269
|
-
# the list of
|
270
|
-
def initialize(
|
271
|
-
@
|
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
|
-
|
276
|
-
|
277
|
-
|
278
|
-
"
|
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
|
-
|
283
|
-
|
284
|
-
|
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
|
290
|
-
|
291
|
-
|
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 [
|
217
|
+
# @param [Location] location
|
297
218
|
# the location (or any subclass) raising this validation error
|
298
|
-
# @param [
|
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
|
-
|
325
|
-
|
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 [
|
250
|
+
# @param [Dependency] locked_dependency
|
333
251
|
# the locked dependency
|
334
|
-
# @param [
|
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 [
|
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: #{
|
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 =
|
492
|
-
msg
|
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.
|
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
|
-
|
539
|
-
|
540
|
-
|
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
|
548
|
-
|
549
|
-
|
550
|
-
|
551
|
-
|
552
|
-
|
553
|
-
|
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
|