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.
@@ -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