berkshelf 2.0.4 → 2.0.5
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.
- data/CHANGELOG.md +6 -0
- data/features/lockfile.feature +34 -11
- data/features/update_command.feature +10 -20
- data/lib/berkshelf/cookbook_source.rb +0 -4
- data/lib/berkshelf/downloader.rb +1 -22
- data/lib/berkshelf/errors.rb +17 -0
- data/lib/berkshelf/lockfile.rb +21 -12
- data/lib/berkshelf/resolver.rb +11 -2
- data/lib/berkshelf/version.rb +1 -1
- data/spec/unit/berkshelf/cookbook_source_spec.rb +1 -7
- data/spec/unit/berkshelf/resolver_spec.rb +2 -0
- metadata +2 -2
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,9 @@
|
|
1
|
+
# 2.0.5
|
2
|
+
|
3
|
+
* Improve speed of resolution when a lockfile is present
|
4
|
+
* Gracefully fail when a lockfile is present but empty
|
5
|
+
* Fix issue where locked version was not honored if the cookbook store was empty
|
6
|
+
|
1
7
|
# 2.0.4
|
2
8
|
|
3
9
|
* Fix bug where community cookbooks compressed with bzip2 would not download and install
|
data/features/lockfile.feature
CHANGED
@@ -17,7 +17,6 @@ Feature: Creating and reading the Berkshelf lockfile
|
|
17
17
|
"sha":"80396ed07db133e0192593adebb360c27eed88c2",
|
18
18
|
"sources":{
|
19
19
|
"fake":{
|
20
|
-
"constraint":"= 1.0.0",
|
21
20
|
"locked_version":"1.0.0"
|
22
21
|
}
|
23
22
|
}
|
@@ -44,7 +43,6 @@ Feature: Creating and reading the Berkshelf lockfile
|
|
44
43
|
"sha": "374a3d22920abae4a6d620a14a32b90d8babda8f",
|
45
44
|
"sources": {
|
46
45
|
"fake": {
|
47
|
-
"constraint": "= 1.0.0",
|
48
46
|
"locked_version": "1.0.0"
|
49
47
|
}
|
50
48
|
}
|
@@ -69,7 +67,6 @@ Feature: Creating and reading the Berkshelf lockfile
|
|
69
67
|
"sha":"ebf27d476739b5aba7e7e8a61de23b3330e20a7d",
|
70
68
|
"sources":{
|
71
69
|
"fake":{
|
72
|
-
"constraint":"= 0.0.0",
|
73
70
|
"path":"./fake"
|
74
71
|
}
|
75
72
|
}
|
@@ -92,11 +89,9 @@ Feature: Creating and reading the Berkshelf lockfile
|
|
92
89
|
"sha":"80396ed07db133e0192593adebb360c27eed88c2",
|
93
90
|
"sources":{
|
94
91
|
"fake":{
|
95
|
-
"constraint":"= 1.0.0",
|
96
92
|
"locked_version":"1.0.0"
|
97
93
|
},
|
98
94
|
"dep":{
|
99
|
-
"constraint":"~> 1.0.0",
|
100
95
|
"locked_version":"1.0.0"
|
101
96
|
}
|
102
97
|
}
|
@@ -117,7 +112,6 @@ Feature: Creating and reading the Berkshelf lockfile
|
|
117
112
|
"sha":"e42f8e41a5e646bd86591c5b7ec25442736b87fd",
|
118
113
|
"sources":{
|
119
114
|
"berkshelf-cookbook-fixture":{
|
120
|
-
"constraint":"~> 1.0.0",
|
121
115
|
"locked_version":"1.0.0"
|
122
116
|
}
|
123
117
|
}
|
@@ -130,7 +124,6 @@ Feature: Creating and reading the Berkshelf lockfile
|
|
130
124
|
"sha":"e42f8e41a5e646bd86591c5b7ec25442736b87fd",
|
131
125
|
"sources":{
|
132
126
|
"berkshelf-cookbook-fixture":{
|
133
|
-
"constraint":"~> 1.0.0",
|
134
127
|
"locked_version":"1.0.0"
|
135
128
|
}
|
136
129
|
}
|
@@ -152,7 +145,6 @@ Feature: Creating and reading the Berkshelf lockfile
|
|
152
145
|
"sha":"3dced4fcd9c3f72b68e746190aaa1140bdc6cc3d",
|
153
146
|
"sources":{
|
154
147
|
"berkshelf-cookbook-fixture":{
|
155
|
-
"constraint":"~> 0.1",
|
156
148
|
"locked_version":"0.1.0"
|
157
149
|
}
|
158
150
|
}
|
@@ -165,7 +157,6 @@ Feature: Creating and reading the Berkshelf lockfile
|
|
165
157
|
"sha":"b2714a4f9bdf500cb20267067160a0b3c1d8404c",
|
166
158
|
"sources":{
|
167
159
|
"berkshelf-cookbook-fixture":{
|
168
|
-
"constraint":"~> 0.1",
|
169
160
|
"locked_version":"0.2.0"
|
170
161
|
}
|
171
162
|
}
|
@@ -186,7 +177,6 @@ Feature: Creating and reading the Berkshelf lockfile
|
|
186
177
|
"sha":"c6438d7590f4d695d8abae83ff22586ba6d3a52e",
|
187
178
|
"sources":{
|
188
179
|
"berkshelf-cookbook-fixture":{
|
189
|
-
"constraint":"= 1.0.0",
|
190
180
|
"locked_version":"1.0.0"
|
191
181
|
}
|
192
182
|
}
|
@@ -199,7 +189,6 @@ Feature: Creating and reading the Berkshelf lockfile
|
|
199
189
|
"sha":"c6438d7590f4d695d8abae83ff22586ba6d3a52e",
|
200
190
|
"sources":{
|
201
191
|
"berkshelf-cookbook-fixture":{
|
202
|
-
"constraint":"= 1.0.0",
|
203
192
|
"locked_version":"1.0.0"
|
204
193
|
}
|
205
194
|
}
|
@@ -441,3 +430,37 @@ Feature: Creating and reading the Berkshelf lockfile
|
|
441
430
|
Try running `berks update berkshelf-cookbook-fixture, which will try to find 'berkshelf-cookbook-fixture' matching '~> 1.3.0'
|
442
431
|
"""
|
443
432
|
And the CLI should exit with the status code for error "OutdatedCookbookSource"
|
433
|
+
|
434
|
+
Scenario: Installing when the Lockfile is empty
|
435
|
+
Given the cookbook store has the cookbooks:
|
436
|
+
| fake | 1.0.0 |
|
437
|
+
And I write to "Berksfile" with:
|
438
|
+
"""
|
439
|
+
site :opscode
|
440
|
+
cookbook 'fake', '1.0.0'
|
441
|
+
"""
|
442
|
+
And an empty file named "Berksfile.lock"
|
443
|
+
When I successfully run `berks install`
|
444
|
+
Then the output should contain:
|
445
|
+
"""
|
446
|
+
Using fake (1.0.0)
|
447
|
+
"""
|
448
|
+
And the exit status should be 0
|
449
|
+
|
450
|
+
Scenario: Installing when the Lockfile is in a bad state
|
451
|
+
Given I write to "Berksfile" with:
|
452
|
+
"""
|
453
|
+
site :opscode
|
454
|
+
cookbook 'fake', '1.0.0'
|
455
|
+
"""
|
456
|
+
Given I write to "Berksfile.lock" with:
|
457
|
+
"""
|
458
|
+
this is totally not valid
|
459
|
+
"""
|
460
|
+
When I run `berks install`
|
461
|
+
Then the output should contain:
|
462
|
+
"""
|
463
|
+
Error reading the Berkshelf lockfile `Berksfile.lock` (JSON::ParserError)
|
464
|
+
"""
|
465
|
+
And the CLI should exit with the status code for error "LockfileParserError"
|
466
|
+
|
@@ -23,8 +23,7 @@ Feature: Updating a cookbook defined by a Berksfile
|
|
23
23
|
"sha":"b2714a4f9bdf500cb20267067160a0b3c1d8404c",
|
24
24
|
"sources":{
|
25
25
|
"berkshelf-cookbook-fixture":{
|
26
|
-
"locked_version":"0.1.0"
|
27
|
-
"constraint":"~> 0.1"
|
26
|
+
"locked_version":"0.1.0"
|
28
27
|
}
|
29
28
|
}
|
30
29
|
}
|
@@ -47,12 +46,10 @@ Feature: Updating a cookbook defined by a Berksfile
|
|
47
46
|
"sha":"69b2e00e970d2bb6a9b1d09aeb3e6a17ef3df955",
|
48
47
|
"sources":{
|
49
48
|
"berkshelf-cookbook-fixture":{
|
50
|
-
"locked_version":"0.1.0"
|
51
|
-
"constraint":"~> 0.1"
|
49
|
+
"locked_version":"0.1.0"
|
52
50
|
},
|
53
51
|
"hostsfile":{
|
54
|
-
"locked_version":"1.0.1"
|
55
|
-
"constraint":"= 1.0.1"
|
52
|
+
"locked_version":"1.0.1"
|
56
53
|
}
|
57
54
|
}
|
58
55
|
}
|
@@ -64,12 +61,10 @@ Feature: Updating a cookbook defined by a Berksfile
|
|
64
61
|
"sha":"69b2e00e970d2bb6a9b1d09aeb3e6a17ef3df955",
|
65
62
|
"sources":{
|
66
63
|
"berkshelf-cookbook-fixture":{
|
67
|
-
"locked_version":"0.2.0"
|
68
|
-
"constraint":"~> 0.1"
|
64
|
+
"locked_version":"0.2.0"
|
69
65
|
},
|
70
66
|
"hostsfile":{
|
71
|
-
"locked_version":"1.0.1"
|
72
|
-
"constraint":"~> 1.0.0"
|
67
|
+
"locked_version":"1.0.1"
|
73
68
|
}
|
74
69
|
}
|
75
70
|
}
|
@@ -92,12 +87,10 @@ Feature: Updating a cookbook defined by a Berksfile
|
|
92
87
|
"sha":"69b2e00e970d2bb6a9b1d09aeb3e6a17ef3df955",
|
93
88
|
"sources":{
|
94
89
|
"berkshelf-cookbook-fixture":{
|
95
|
-
"locked_version":"0.1.0"
|
96
|
-
"constraint":"~> 0.1"
|
90
|
+
"locked_version":"0.1.0"
|
97
91
|
},
|
98
92
|
"hostsfile":{
|
99
|
-
"locked_version":"1.0.0"
|
100
|
-
"constraint":"~> 1.0.0"
|
93
|
+
"locked_version":"1.0.0"
|
101
94
|
}
|
102
95
|
}
|
103
96
|
}
|
@@ -109,12 +102,10 @@ Feature: Updating a cookbook defined by a Berksfile
|
|
109
102
|
"sha":"69b2e00e970d2bb6a9b1d09aeb3e6a17ef3df955",
|
110
103
|
"sources":{
|
111
104
|
"berkshelf-cookbook-fixture":{
|
112
|
-
"locked_version":"0.2.0"
|
113
|
-
"constraint":"~> 0.1"
|
105
|
+
"locked_version":"0.2.0"
|
114
106
|
},
|
115
107
|
"hostsfile":{
|
116
|
-
"locked_version":"1.0.0"
|
117
|
-
"constraint":"~> 1.0.0"
|
108
|
+
"locked_version":"1.0.0"
|
118
109
|
}
|
119
110
|
}
|
120
111
|
}
|
@@ -134,8 +125,7 @@ Feature: Updating a cookbook defined by a Berksfile
|
|
134
125
|
"sha":"23150cfe61b7b86882013c8664883058560b899d",
|
135
126
|
"sources":{
|
136
127
|
"berkshelf-cookbook-fixture":{
|
137
|
-
"locked_version":"0.1.0"
|
138
|
-
"constraint":"~> 0.1"
|
128
|
+
"locked_version":"0.1.0"
|
139
129
|
}
|
140
130
|
}
|
141
131
|
}
|
@@ -198,10 +198,6 @@ module Berkshelf
|
|
198
198
|
h[:locked_version] = locked_version.to_s
|
199
199
|
end
|
200
200
|
|
201
|
-
unless version_constraint.to_s == DEFAULT_CONSTRAINT
|
202
|
-
h[:constraint] = version_constraint.to_s
|
203
|
-
end
|
204
|
-
|
205
201
|
if location.kind_of?(SiteLocation)
|
206
202
|
h[:site] = location.api_uri if location.api_uri != CommunityREST::V1_API
|
207
203
|
end
|
data/lib/berkshelf/downloader.rb
CHANGED
@@ -116,31 +116,10 @@ module Berkshelf
|
|
116
116
|
# @return [Berkshelf::CachedCookbook, nil]
|
117
117
|
# the downloaded cached cookbook, or nil if one was not found
|
118
118
|
def download_location(source, location, raise_if_not_found = false)
|
119
|
-
|
119
|
+
location.download(storage_path)
|
120
120
|
rescue Berkshelf::CookbookNotFound
|
121
121
|
raise if raise_if_not_found
|
122
122
|
nil
|
123
123
|
end
|
124
|
-
|
125
|
-
# Load the cached cookbook from the cookbook store.
|
126
|
-
#
|
127
|
-
# @param [Berkshelf::CookbookSource] source
|
128
|
-
# the source to find in the cache
|
129
|
-
#
|
130
|
-
# @return [Berkshelf::CachedCookbook, nil]
|
131
|
-
def from_cache(source)
|
132
|
-
# Can't safely read a git location from cache
|
133
|
-
return nil if source.location.kind_of?(Berkshelf::GitLocation)
|
134
|
-
|
135
|
-
if source.locked_version
|
136
|
-
cookbook = cookbook_store.cookbook_path(source.name, source.locked_version)
|
137
|
-
path = File.expand_path(File.join(storage_path, cookbook))
|
138
|
-
|
139
|
-
return nil unless File.exists?(path)
|
140
|
-
return Berkshelf::CachedCookbook.from_path(path, name: source.name)
|
141
|
-
end
|
142
|
-
|
143
|
-
cookbook_store.satisfy(source.name, source.version_constraint)
|
144
|
-
end
|
145
124
|
end
|
146
125
|
end
|
data/lib/berkshelf/errors.rb
CHANGED
@@ -379,4 +379,21 @@ module Berkshelf
|
|
379
379
|
"No #{@type.capitalize} config file found at: '#{@path}'!"
|
380
380
|
end
|
381
381
|
end
|
382
|
+
|
383
|
+
class LockfileParserError < BerkshelfError
|
384
|
+
status_code(136)
|
385
|
+
|
386
|
+
# @param [String] lockfile
|
387
|
+
# the path to the Lockfile
|
388
|
+
# @param [~Exception] original
|
389
|
+
# the original exception class
|
390
|
+
def initialize(lockfile, original)
|
391
|
+
@lockfile = Pathname.new(lockfile.to_s).basename.to_s
|
392
|
+
@original = original
|
393
|
+
end
|
394
|
+
|
395
|
+
def to_s
|
396
|
+
"Error reading the Berkshelf lockfile `#{@lockfile}` (#{@original.class})"
|
397
|
+
end
|
398
|
+
end
|
382
399
|
end
|
data/lib/berkshelf/lockfile.rb
CHANGED
@@ -33,19 +33,9 @@ module Berkshelf
|
|
33
33
|
|
34
34
|
# Load the lockfile from file system.
|
35
35
|
def load!
|
36
|
-
contents = File.read(filepath)
|
37
|
-
|
38
|
-
begin
|
39
|
-
hash = JSON.parse(contents, symbolize_names: true)
|
40
|
-
rescue JSON::ParserError
|
41
|
-
if contents =~ /^cookbook ["'](.+)["']/
|
42
|
-
Berkshelf.ui.warn 'You are using the old lockfile format. Attempting to convert...'
|
43
|
-
hash = LockfileLegacy.parse(berksfile, contents)
|
44
|
-
else
|
45
|
-
raise
|
46
|
-
end
|
47
|
-
end
|
36
|
+
contents = File.read(filepath).strip
|
48
37
|
|
38
|
+
hash = parse(contents)
|
49
39
|
@sha = hash[:sha]
|
50
40
|
|
51
41
|
hash[:sources].each do |name, options|
|
@@ -168,6 +158,25 @@ module Berkshelf
|
|
168
158
|
|
169
159
|
private
|
170
160
|
|
161
|
+
# Parse the given string as JSON.
|
162
|
+
#
|
163
|
+
# @param [String] contents
|
164
|
+
#
|
165
|
+
# @return [Hash]
|
166
|
+
def parse(contents)
|
167
|
+
# Ruby's JSON.parse cannot handle an empty string/file
|
168
|
+
return { sha: nil, sources: [] } if contents.strip.empty?
|
169
|
+
|
170
|
+
JSON.parse(contents, symbolize_names: true)
|
171
|
+
rescue Exception => e
|
172
|
+
if e.class == JSON::ParserError && contents =~ /^cookbook ["'](.+)["']/
|
173
|
+
Berkshelf.ui.warn 'You are using the old lockfile format. Attempting to convert...'
|
174
|
+
return LockfileLegacy.parse(berksfile, contents)
|
175
|
+
else
|
176
|
+
raise Berkshelf::LockfileParserError.new(filepath, e)
|
177
|
+
end
|
178
|
+
end
|
179
|
+
|
171
180
|
# Save the contents of the lockfile to disk.
|
172
181
|
def save
|
173
182
|
File.open(filepath, 'w') do |file|
|
data/lib/berkshelf/resolver.rb
CHANGED
@@ -154,9 +154,13 @@ module Berkshelf
|
|
154
154
|
# @return [Boolean]
|
155
155
|
def use_source(source)
|
156
156
|
name = source.name
|
157
|
-
|
157
|
+
locked = source.locked_version
|
158
158
|
location = source.location
|
159
159
|
|
160
|
+
# Lock the version constraint if a locked version was supplied
|
161
|
+
source.version_constraint = Solve::Constraint.new(locked.to_s) if locked
|
162
|
+
constraint = source.version_constraint
|
163
|
+
|
160
164
|
if source.downloaded?
|
161
165
|
cached = source.cached_cookbook
|
162
166
|
location.validate_cached(cached)
|
@@ -165,7 +169,12 @@ module Berkshelf
|
|
165
169
|
elsif location.is_a?(GitLocation)
|
166
170
|
false
|
167
171
|
else
|
168
|
-
|
172
|
+
# If a locked version if specified, it must exist
|
173
|
+
if locked
|
174
|
+
cached = downloader.cookbook_store.cookbook(name, locked)
|
175
|
+
else
|
176
|
+
cached = downloader.cookbook_store.satisfy(name, constraint)
|
177
|
+
end
|
169
178
|
|
170
179
|
if cached
|
171
180
|
get_source(source).cached_cookbook = cached
|
data/lib/berkshelf/version.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
|
1
2
|
require 'spec_helper'
|
2
3
|
|
3
4
|
describe Berkshelf::CookbookSource do
|
@@ -260,13 +261,6 @@ describe Berkshelf::CookbookSource do
|
|
260
261
|
end
|
261
262
|
end
|
262
263
|
|
263
|
-
it 'includes the constraint' do
|
264
|
-
subject.version_constraint = '~> 1.0.0'
|
265
|
-
|
266
|
-
expect(hash).to have_key(:constraint)
|
267
|
-
expect(hash[:constraint]).to eq('~> 1.0.0')
|
268
|
-
end
|
269
|
-
|
270
264
|
it 'includes the locked version' do
|
271
265
|
subject.cached_cookbook = double('cached', version: '1.2.3')
|
272
266
|
|
@@ -7,6 +7,8 @@ describe Berkshelf::Resolver, :chef_server, vcr: { record: :new_episodes, serial
|
|
7
7
|
double('source',
|
8
8
|
name: 'mysql',
|
9
9
|
version_constraint: Solve::Constraint.new('= 1.2.4'),
|
10
|
+
:version_constraint= => nil,
|
11
|
+
locked_version: '1.2.4',
|
10
12
|
downloaded?: true,
|
11
13
|
cached_cookbook: double('mysql-cookbook',
|
12
14
|
name: 'mysql-1.2.4',
|
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.
|
4
|
+
version: 2.0.5
|
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-
|
16
|
+
date: 2013-06-21 00:00:00.000000000 Z
|
17
17
|
dependencies:
|
18
18
|
- !ruby/object:Gem::Dependency
|
19
19
|
name: activesupport
|