berkshelf 2.0.4 → 2.0.5

Sign up to get free protection for your applications and to get access to all the features.
@@ -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
@@ -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
@@ -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
- from_cache(source) || location.download(storage_path)
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
@@ -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
@@ -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|
@@ -154,9 +154,13 @@ module Berkshelf
154
154
  # @return [Boolean]
155
155
  def use_source(source)
156
156
  name = source.name
157
- constraint = source.version_constraint
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
- cached = downloader.cookbook_store.satisfy(name, constraint)
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
@@ -1,3 +1,3 @@
1
1
  module Berkshelf
2
- VERSION = "2.0.4"
2
+ VERSION = "2.0.5"
3
3
  end
@@ -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
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-17 00:00:00.000000000 Z
16
+ date: 2013-06-21 00:00:00.000000000 Z
17
17
  dependencies:
18
18
  - !ruby/object:Gem::Dependency
19
19
  name: activesupport