berkshelf 3.0.0.beta9 → 3.0.0.rc1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +4 -0
- data/README.md +69 -48
- data/berkshelf.gemspec +3 -3
- data/features/commands/update.feature +41 -1
- data/features/commands/upload.feature +61 -11
- data/features/lifecycle.feature +93 -0
- data/generator_files/CHANGELOG.md.erb +8 -4
- data/generator_files/gitignore.erb +7 -2
- data/generator_files/metadata.rb.erb +2 -2
- data/lib/berkshelf.rb +2 -0
- data/lib/berkshelf/base_generator.rb +18 -0
- data/lib/berkshelf/berksfile.rb +11 -103
- data/lib/berkshelf/cli.rb +6 -4
- data/lib/berkshelf/cookbook_generator.rb +20 -9
- data/lib/berkshelf/formatters/base.rb +2 -2
- data/lib/berkshelf/formatters/human.rb +3 -3
- data/lib/berkshelf/formatters/json.rb +2 -2
- data/lib/berkshelf/init_generator.rb +1 -7
- data/lib/berkshelf/installer.rb +2 -1
- data/lib/berkshelf/lockfile.rb +88 -40
- data/lib/berkshelf/logger.rb +2 -2
- data/lib/berkshelf/resolver.rb +4 -1
- data/lib/berkshelf/uploader.rb +122 -0
- data/lib/berkshelf/version.rb +1 -1
- data/spec/unit/berkshelf/berksfile_spec.rb +18 -169
- data/spec/unit/berkshelf/cookbook_generator_spec.rb +2 -2
- data/spec/unit/berkshelf/formatters/base_spec.rb +1 -1
- data/spec/unit/berkshelf/ui_spec.rb +6 -7
- data/spec/unit/berkshelf/uploader_spec.rb +190 -0
- metadata +13 -11
- data/gem_graph.png +0 -0
@@ -1,5 +1,9 @@
|
|
1
|
-
#
|
2
|
-
This file is used to list changes made in each version of the <%= name %> cookbook.
|
1
|
+
# 0.1.0
|
3
2
|
|
4
|
-
|
5
|
-
|
3
|
+
Initial release of <%= name %>
|
4
|
+
|
5
|
+
* Enhancements
|
6
|
+
* an enhancement
|
7
|
+
|
8
|
+
* Bug Fixes
|
9
|
+
* a bug fix
|
@@ -3,9 +3,9 @@ maintainer '<%= maintainer %>'
|
|
3
3
|
maintainer_email '<%= maintainer_email %>'
|
4
4
|
license '<%= license_name %>'
|
5
5
|
description 'Installs/Configures <%= name %>'
|
6
|
-
long_description
|
6
|
+
long_description 'Installs/Configures <%= name %>'
|
7
7
|
<% if options[:scmversion] -%>
|
8
|
-
version IO.read(File.join(File.dirname(__FILE__), 'VERSION'))
|
8
|
+
version IO.read(File.join(File.dirname(__FILE__), 'VERSION'))
|
9
9
|
<% else -%>
|
10
10
|
version '0.1.0'
|
11
11
|
<% end -%>
|
data/lib/berkshelf.rb
CHANGED
@@ -24,6 +24,8 @@ module Berkshelf
|
|
24
24
|
autoload :Logging, 'berkshelf/mixin/logging'
|
25
25
|
end
|
26
26
|
|
27
|
+
autoload :Uploader, 'berkshelf/uploader'
|
28
|
+
|
27
29
|
autoload :BaseFormatter, 'berkshelf/formatters/base'
|
28
30
|
autoload :HumanFormatter, 'berkshelf/formatters/human'
|
29
31
|
autoload :JsonFormatter, 'berkshelf/formatters/json'
|
@@ -8,12 +8,30 @@ module Berkshelf
|
|
8
8
|
end
|
9
9
|
end
|
10
10
|
|
11
|
+
# A list of cookbook patterns accepted by generators inheriting from
|
12
|
+
# this generator.
|
13
|
+
#
|
14
|
+
# @return [Array<String>]
|
15
|
+
PATTERNS = [
|
16
|
+
"environment",
|
17
|
+
"application",
|
18
|
+
"library",
|
19
|
+
"wrapper"
|
20
|
+
].freeze
|
21
|
+
|
11
22
|
shell = Berkshelf.ui
|
12
23
|
|
13
24
|
argument :path,
|
14
25
|
type: :string,
|
15
26
|
required: true
|
16
27
|
|
28
|
+
class_option :pattern,
|
29
|
+
type: :string,
|
30
|
+
default: "application",
|
31
|
+
desc: "Modifies the generated skeleton based on the given pattern.",
|
32
|
+
aliases: "-p",
|
33
|
+
enum: BaseGenerator::PATTERNS
|
34
|
+
|
17
35
|
include Thor::Actions
|
18
36
|
|
19
37
|
private
|
data/lib/berkshelf/berksfile.rb
CHANGED
@@ -378,18 +378,22 @@ module Berkshelf
|
|
378
378
|
# @option options [String, Array<String>] :cookbooks
|
379
379
|
# Names of the cookbooks to retrieve dependencies for
|
380
380
|
def update(*names)
|
381
|
+
validate_lockfile_present!
|
381
382
|
validate_cookbook_names!(names)
|
382
383
|
|
384
|
+
Berkshelf.log.info "Updating cookbooks"
|
385
|
+
|
383
386
|
# Calculate the list of cookbooks to unlock
|
384
387
|
if names.empty?
|
385
|
-
|
388
|
+
Berkshelf.log.debug " Unlocking all the things!"
|
389
|
+
lockfile.unlock_all
|
386
390
|
else
|
387
|
-
|
391
|
+
names.each do |name|
|
392
|
+
Berkshelf.log.debug " Unlocking #{name}"
|
393
|
+
lockfile.unlock(name, true)
|
394
|
+
end
|
388
395
|
end
|
389
396
|
|
390
|
-
# Unlock any/all specified cookbooks
|
391
|
-
list.each { |dependency| lockfile.unlock(dependency) }
|
392
|
-
|
393
397
|
# NOTE: We intentionally do NOT pass options to the installer
|
394
398
|
self.install
|
395
399
|
end
|
@@ -529,24 +533,11 @@ module Berkshelf
|
|
529
533
|
# @return [Array<CachedCookbook>]
|
530
534
|
# the list of cookbooks that were uploaded to the Chef Server
|
531
535
|
def upload(*args)
|
532
|
-
options = args.last.is_a?(Hash) ? args.pop : {}
|
533
|
-
names = args.flatten
|
534
|
-
|
535
536
|
validate_lockfile_present!
|
536
537
|
validate_lockfile_trusted!
|
537
538
|
validate_dependencies_installed!
|
538
|
-
validate_cookbook_names!(names)
|
539
539
|
|
540
|
-
|
541
|
-
if names.empty?
|
542
|
-
list = dependencies
|
543
|
-
else
|
544
|
-
list = dependencies.select { |dependency| names.include?(dependency.name) }
|
545
|
-
end
|
546
|
-
|
547
|
-
cookbooks = cookbooks_for_upload(list)
|
548
|
-
ridley_upload(cookbooks, options)
|
549
|
-
cookbooks
|
540
|
+
Uploader.new(self, *args).run
|
550
541
|
end
|
551
542
|
|
552
543
|
# Package the given cookbook for distribution outside of berkshelf. If the
|
@@ -651,73 +642,6 @@ module Berkshelf
|
|
651
642
|
|
652
643
|
private
|
653
644
|
|
654
|
-
def ridley_upload(cookbooks, options = {})
|
655
|
-
options = {
|
656
|
-
force: false,
|
657
|
-
freeze: true,
|
658
|
-
halt_on_frozen: false,
|
659
|
-
validate: true,
|
660
|
-
}.merge(options)
|
661
|
-
|
662
|
-
skipped = []
|
663
|
-
|
664
|
-
Berkshelf.ridley_connection(options) do |conn|
|
665
|
-
cookbooks.each do |cookbook|
|
666
|
-
Berkshelf.formatter.upload(cookbook, conn)
|
667
|
-
validate_files!(cookbook)
|
668
|
-
|
669
|
-
begin
|
670
|
-
conn.cookbook.upload(cookbook.path, {
|
671
|
-
force: options[:force],
|
672
|
-
freeze: options[:freeze],
|
673
|
-
name: cookbook.cookbook_name,
|
674
|
-
validate: options[:validate]
|
675
|
-
})
|
676
|
-
rescue Ridley::Errors::FrozenCookbook => ex
|
677
|
-
if options[:halt_on_frozen]
|
678
|
-
raise FrozenCookbook.new(cookbook)
|
679
|
-
end
|
680
|
-
|
681
|
-
Berkshelf.formatter.skip(cookbook, conn)
|
682
|
-
skipped << cookbook
|
683
|
-
end
|
684
|
-
end
|
685
|
-
end
|
686
|
-
|
687
|
-
unless skipped.empty?
|
688
|
-
Berkshelf.formatter.msg "Skipped uploading some cookbooks because they" <<
|
689
|
-
" already exist on the remote server and are frozen. Re-run with the `--force`" <<
|
690
|
-
" flag to force overwrite these cookbooks:" <<
|
691
|
-
"\n\n" <<
|
692
|
-
" * " << skipped.map { |c| "#{c.cookbook_name} (#{c.version})" }.join("\n * ")
|
693
|
-
end
|
694
|
-
end
|
695
|
-
|
696
|
-
# Filter the given dependencies for upload. The dependencies of a cookbook
|
697
|
-
# will always be included in the filtered results, even if that
|
698
|
-
# dependency's name is not explicitly provided.
|
699
|
-
#
|
700
|
-
# @param [Array<Dependency>] dependencies
|
701
|
-
# the list of dependencies to filter for upload
|
702
|
-
#
|
703
|
-
# @return [Array<CachedCookbook>]
|
704
|
-
# the cookbook objects for uploading
|
705
|
-
def cookbooks_for_upload(dependencies)
|
706
|
-
dependencies.reduce({}) do |hash, dependency|
|
707
|
-
if hash[dependency.name].nil?
|
708
|
-
# TODO: make this a configurable option for advanced users to save
|
709
|
-
# time.
|
710
|
-
lockfile.graph.find(dependency).dependencies.each do |direct, _|
|
711
|
-
hash[direct] ||= lockfile.retrieve(direct)
|
712
|
-
end
|
713
|
-
|
714
|
-
hash[dependency.name] = lockfile.retrieve(dependency)
|
715
|
-
end
|
716
|
-
|
717
|
-
hash
|
718
|
-
end.values
|
719
|
-
end
|
720
|
-
|
721
645
|
# Ensure the lockfile is present on disk.
|
722
646
|
#
|
723
647
|
# @raise [LockfileNotFound]
|
@@ -769,27 +693,11 @@ module Berkshelf
|
|
769
693
|
# @raise [DependencyNotFound]
|
770
694
|
# if a cookbook name is given that does not exist
|
771
695
|
def validate_cookbook_names!(names)
|
772
|
-
missing = names -
|
696
|
+
missing = names - lockfile.graph.locks.keys
|
773
697
|
|
774
698
|
unless missing.empty?
|
775
699
|
raise DependencyNotFound.new(missing)
|
776
700
|
end
|
777
701
|
end
|
778
|
-
|
779
|
-
# Validate that the given cookbook does not have "bad" files. Currently
|
780
|
-
# this means including spaces in filenames (such as recipes)
|
781
|
-
#
|
782
|
-
# @param [CachedCookbook] cookbook
|
783
|
-
# the Cookbook to validate
|
784
|
-
def validate_files!(cookbook)
|
785
|
-
path = cookbook.path.to_s
|
786
|
-
|
787
|
-
files = Dir.glob(File.join(path, '**', '*.rb')).select do |f|
|
788
|
-
parent = Pathname.new(path).dirname.to_s
|
789
|
-
f.gsub(parent, '') =~ /[[:space:]]/
|
790
|
-
end
|
791
|
-
|
792
|
-
raise InvalidCookbookFiles.new(cookbook, files) unless files.empty?
|
793
|
-
end
|
794
702
|
end
|
795
703
|
end
|
data/lib/berkshelf/cli.rb
CHANGED
@@ -197,7 +197,7 @@ module Berkshelf
|
|
197
197
|
method_option :halt_on_frozen,
|
198
198
|
type: :boolean,
|
199
199
|
default: false,
|
200
|
-
desc: '
|
200
|
+
desc: 'Exit with a non zero exit code if the Chef Server already has the version of the cookbook(s).'
|
201
201
|
desc 'upload [COOKBOOKS]', 'Upload the cookbook specified in the Berksfile to the Chef Server'
|
202
202
|
def upload(*names)
|
203
203
|
berksfile = Berksfile.from_options(options)
|
@@ -279,6 +279,7 @@ module Berkshelf
|
|
279
279
|
|
280
280
|
Berkshelf.formatter.msg 'Successfully initialized'
|
281
281
|
end
|
282
|
+
tasks['init'].options = Berkshelf::InitGenerator.class_options
|
282
283
|
|
283
284
|
method_option :berksfile,
|
284
285
|
type: :string,
|
@@ -385,12 +386,13 @@ module Berkshelf
|
|
385
386
|
Berkshelf.formatter.version
|
386
387
|
end
|
387
388
|
|
388
|
-
desc 'cookbook NAME', 'Create a skeleton for a new cookbook'
|
389
|
-
def cookbook(name)
|
389
|
+
desc 'cookbook NAME [PATH]', 'Create a skeleton for a new cookbook'
|
390
|
+
def cookbook(name, path = nil)
|
391
|
+
path = File.join(Dir.pwd, name) if path.nil?
|
390
392
|
Berkshelf.formatter.deprecation '--git is now the default' if options[:git]
|
391
393
|
Berkshelf.formatter.deprecation '--vagrant is now the default' if options[:vagrant]
|
392
394
|
|
393
|
-
Berkshelf::CookbookGenerator.new([
|
395
|
+
Berkshelf::CookbookGenerator.new([path, name], options).invoke_all
|
394
396
|
end
|
395
397
|
tasks['cookbook'].options = Berkshelf::CookbookGenerator.class_options
|
396
398
|
|
@@ -48,15 +48,26 @@ module Berkshelf
|
|
48
48
|
default: Berkshelf.config.cookbook.email
|
49
49
|
|
50
50
|
def generate
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
51
|
+
case options[:pattern]
|
52
|
+
when "library"
|
53
|
+
empty_directory target.join("libraries")
|
54
|
+
empty_directory target.join("providers")
|
55
|
+
empty_directory target.join("resources")
|
56
|
+
when "wrapper"
|
57
|
+
empty_directory target.join("attributes")
|
58
|
+
empty_directory target.join("recipes")
|
59
|
+
template "default_recipe.erb", target.join("recipes/default.rb")
|
60
|
+
when "environment", "application"
|
61
|
+
empty_directory target.join("files/default")
|
62
|
+
empty_directory target.join("templates/default")
|
63
|
+
empty_directory target.join("attributes")
|
64
|
+
empty_directory target.join("libraries")
|
65
|
+
empty_directory target.join("providers")
|
66
|
+
empty_directory target.join("recipes")
|
67
|
+
empty_directory target.join("resources")
|
68
|
+
template "default_recipe.erb", target.join("recipes/default.rb")
|
69
|
+
end
|
70
|
+
|
60
71
|
template 'metadata.rb.erb', target.join('metadata.rb')
|
61
72
|
template license_file, target.join('LICENSE')
|
62
73
|
template 'README.md.erb', target.join('README.md')
|
@@ -30,8 +30,8 @@ module Berkshelf
|
|
30
30
|
formatter_method :package
|
31
31
|
formatter_method :search
|
32
32
|
formatter_method :show
|
33
|
-
formatter_method :
|
34
|
-
formatter_method :
|
33
|
+
formatter_method :skipping
|
34
|
+
formatter_method :uploaded
|
35
35
|
formatter_method :use
|
36
36
|
formatter_method :vendor
|
37
37
|
formatter_method :version
|
@@ -40,15 +40,15 @@ module Berkshelf
|
|
40
40
|
#
|
41
41
|
# @param [Berkshelf::CachedCookbook] cookbook
|
42
42
|
# @param [Ridley::Connection] conn
|
43
|
-
def
|
44
|
-
Berkshelf.ui.info "
|
43
|
+
def uploaded(cookbook, conn)
|
44
|
+
Berkshelf.ui.info "Uploaded #{cookbook.cookbook_name} (#{cookbook.version}) to: '#{conn.server_url}'"
|
45
45
|
end
|
46
46
|
|
47
47
|
# Output a Cookbook skip message using {Berkshelf.ui}
|
48
48
|
#
|
49
49
|
# @param [Berkshelf::CachedCookbook] cookbook
|
50
50
|
# @param [Ridley::Connection] conn
|
51
|
-
def
|
51
|
+
def skipping(cookbook, conn)
|
52
52
|
Berkshelf.ui.info "Skipping #{cookbook.cookbook_name} (#{cookbook.version}) (frozen)"
|
53
53
|
end
|
54
54
|
|
@@ -66,7 +66,7 @@ module Berkshelf
|
|
66
66
|
#
|
67
67
|
# @param [Berkshelf::CachedCookbook] cookbook
|
68
68
|
# @param [Ridley::Connection] conn
|
69
|
-
def
|
69
|
+
def uploaded(cookbook, conn)
|
70
70
|
name = cookbook.cookbook_name
|
71
71
|
cookbooks[name] ||= {}
|
72
72
|
cookbooks[name][:version] = cookbook.version
|
@@ -77,7 +77,7 @@ module Berkshelf
|
|
77
77
|
#
|
78
78
|
# @param [Berkshelf::CachedCookbook] cookbook
|
79
79
|
# @param [Ridley::Connection] conn
|
80
|
-
def
|
80
|
+
def skipping(cookbook, conn)
|
81
81
|
name = cookbook.cookbook_name
|
82
82
|
cookbooks[name] ||= {}
|
83
83
|
cookbooks[name][:version] = cookbook.version
|
@@ -96,13 +96,7 @@ module Berkshelf
|
|
96
96
|
|
97
97
|
if defined?(Kitchen::Generator::Init)
|
98
98
|
unless options[:skip_test_kitchen]
|
99
|
-
|
100
|
-
# is where we expect until this bug can be addressed:
|
101
|
-
# https://github.com/opscode/test-kitchen/pull/140
|
102
|
-
Dir.chdir target do
|
103
|
-
# Kitchen::Generator::Init.new([], {}, destination_root: target).invoke_all
|
104
|
-
Kitchen::Generator::Init.new([], {}).invoke_all
|
105
|
-
end
|
99
|
+
Kitchen::Generator::Init.new([], {}, destination_root: target).invoke_all
|
106
100
|
end
|
107
101
|
end
|
108
102
|
|
data/lib/berkshelf/installer.rb
CHANGED
@@ -146,7 +146,8 @@ module Berkshelf
|
|
146
146
|
# Add any explicit dependencies for already-downloaded cookbooks (like
|
147
147
|
# path locations)
|
148
148
|
dependencies.each do |dependency|
|
149
|
-
if
|
149
|
+
if dependency.location
|
150
|
+
cookbook = dependency.cached_cookbook
|
150
151
|
Berkshelf.log.debug " Adding explicit dependency on #{cookbook}"
|
151
152
|
resolver.add_explicit_dependencies(cookbook)
|
152
153
|
end
|
data/lib/berkshelf/lockfile.rb
CHANGED
@@ -98,8 +98,6 @@ module Berkshelf
|
|
98
98
|
berksfile.dependencies.each do |dependency|
|
99
99
|
Berkshelf.log.debug "Checking #{dependency}"
|
100
100
|
|
101
|
-
checked[dependency.name] = true
|
102
|
-
|
103
101
|
locked = find(dependency)
|
104
102
|
if locked.nil?
|
105
103
|
Berkshelf.log.debug " Not in lockfile - cannot be trusted!"
|
@@ -152,17 +150,36 @@ module Berkshelf
|
|
152
150
|
# the list of already checked dependencies
|
153
151
|
#
|
154
152
|
# @return [Boolean]
|
155
|
-
def satisfies_transitive?(graph_item, checked)
|
156
|
-
|
157
|
-
return true if checked[name]
|
153
|
+
def satisfies_transitive?(graph_item, checked, level = 0)
|
154
|
+
indent = ' '*(level + 2)
|
158
155
|
|
159
|
-
|
156
|
+
Berkshelf.log.debug "#{indent}Checking transitive dependencies for #{graph_item}"
|
157
|
+
|
158
|
+
if checked[graph_item.name]
|
159
|
+
Berkshelf.log.debug "#{indent} Already checked - skipping"
|
160
|
+
return true
|
161
|
+
end
|
162
|
+
|
163
|
+
graph_item.dependencies.each do |name, constraint|
|
164
|
+
Berkshelf.log.debug "#{indent} Checking #{name} (#{constraint})"
|
160
165
|
|
161
166
|
graphed = graph.find(name)
|
162
|
-
|
167
|
+
if graphed.nil?
|
168
|
+
Berkshelf.log.debug "#{indent} Not graphed - cannot be satisifed"
|
169
|
+
return false
|
170
|
+
end
|
171
|
+
|
172
|
+
unless Semverse::Constraint.new(constraint).satisfies?(graphed.version)
|
173
|
+
Berkshelf.log.debug "#{indent} Version constraint is not satisfied"
|
174
|
+
return false
|
175
|
+
end
|
163
176
|
|
164
|
-
|
165
|
-
|
177
|
+
unless satisfies_transitive?(graphed, checked, level + 2)
|
178
|
+
Berkshelf.log.debug "#{indent} Transitive are not satisifed"
|
179
|
+
return false
|
180
|
+
end
|
181
|
+
|
182
|
+
checked[name] = true
|
166
183
|
end
|
167
184
|
end
|
168
185
|
|
@@ -288,14 +305,22 @@ module Berkshelf
|
|
288
305
|
# dependencies. Then it uses a recursive algorithm to safely remove any
|
289
306
|
# other dependencies from the graph that are no longer needed.
|
290
307
|
#
|
291
|
-
# @raise [CookbookNotFound]
|
292
|
-
# if the provided dependency does not exist
|
293
|
-
#
|
294
308
|
# @param [String] dependency
|
295
309
|
# the name of the cookbook to remove
|
296
|
-
def unlock(dependency)
|
310
|
+
def unlock(dependency, force = false)
|
297
311
|
@dependencies.delete(Dependency.name(dependency))
|
298
|
-
|
312
|
+
|
313
|
+
if force
|
314
|
+
graph.remove(dependency, ignore: graph.locks.keys)
|
315
|
+
else
|
316
|
+
graph.remove(dependency)
|
317
|
+
end
|
318
|
+
end
|
319
|
+
|
320
|
+
# Completely remove all dependencies from the lockfile and underlying graph.
|
321
|
+
def unlock_all
|
322
|
+
@dependencies = {}
|
323
|
+
@graph = Graph.new(self)
|
299
324
|
end
|
300
325
|
|
301
326
|
# Iterate over each top-level dependency defined in the lockfile and
|
@@ -317,58 +342,72 @@ module Berkshelf
|
|
317
342
|
#
|
318
343
|
# @return [Array<Dependency>]
|
319
344
|
def reduce!
|
320
|
-
|
321
|
-
|
322
|
-
|
345
|
+
Berkshelf.log.info "Reducing lockfile"
|
346
|
+
|
347
|
+
Berkshelf.log.debug "Current lockfile:"
|
348
|
+
Berkshelf.log.debug ""
|
349
|
+
to_lock.each_line do |line|
|
350
|
+
Berkshelf.log.debug " #{line.chomp}"
|
351
|
+
end
|
352
|
+
Berkshelf.log.debug ""
|
353
|
+
|
323
354
|
|
324
355
|
# Unlock any locked dependencies that are no longer in the Berksfile
|
356
|
+
Berkshelf.log.debug "Unlocking dependencies no longer in the Berksfile"
|
357
|
+
|
325
358
|
dependencies.each do |dependency|
|
326
|
-
|
327
|
-
|
328
|
-
|
329
|
-
|
330
|
-
|
331
|
-
|
332
|
-
|
333
|
-
# being removed in this reduction). It's a form of science. Don't
|
334
|
-
# question it too much.
|
335
|
-
to_ungraph[dependency.name] = true
|
336
|
-
to_ignore[dependency.name] = true
|
359
|
+
Berkshelf.log.debug " Checking #{dependency}"
|
360
|
+
|
361
|
+
if berksfile.has_dependency?(dependency.name)
|
362
|
+
Berkshelf.log.debug " Skipping unlock for #{dependency.name} (exists in the Berksfile)"
|
363
|
+
else
|
364
|
+
Berkshelf.log.debug " Unlocking #{dependency.name}"
|
365
|
+
unlock(dependency, true)
|
337
366
|
end
|
338
367
|
end
|
339
368
|
|
340
369
|
# Remove any transitive dependencies
|
370
|
+
Berkshelf.log.debug "Removing transitive dependencies"
|
371
|
+
|
341
372
|
berksfile.dependencies.each do |dependency|
|
373
|
+
Berkshelf.log.debug " Checking #{dependency}"
|
374
|
+
|
342
375
|
graphed = graph.find(dependency)
|
343
|
-
|
376
|
+
|
377
|
+
if graphed.nil?
|
378
|
+
Berkshelf.log.debug " Skipping (not graphed)"
|
379
|
+
next
|
380
|
+
end
|
344
381
|
|
345
382
|
unless dependency.version_constraint.satisfies?(graphed.version)
|
383
|
+
Berkshelf.log.debug " Constraints are not satisfied!"
|
346
384
|
raise OutdatedDependency.new(graphed, dependency)
|
347
385
|
end
|
348
386
|
|
349
387
|
if cookbook = dependency.cached_cookbook
|
388
|
+
Berkshelf.log.debug " Cached cookbook exists"
|
389
|
+
Berkshelf.log.debug " Checking dependencies on the cached cookbook"
|
390
|
+
|
350
391
|
graphed.dependencies.each do |name, constraint|
|
392
|
+
Berkshelf.log.debug " Checking #{name} (#{constraint})"
|
393
|
+
|
351
394
|
# Unless the cookbook still depends on this key, we want to queue it
|
352
395
|
# for unlocking. This is the magic that prevents transitive
|
353
396
|
# dependency leaking.
|
354
397
|
unless cookbook.dependencies.has_key?(name)
|
355
|
-
|
356
|
-
|
357
|
-
# We also want to ignore the top-level dependency. We can no
|
358
|
-
# longer trust the graph that we have been given for that
|
359
|
-
# dependency and therefore need to reduce it.
|
360
|
-
to_ignore[dependency.name] = true
|
398
|
+
Berkshelf.log.debug " Not found!"
|
399
|
+
unlock(name, true)
|
361
400
|
end
|
362
401
|
end
|
363
402
|
end
|
364
403
|
end
|
365
404
|
|
366
|
-
|
367
|
-
|
368
|
-
|
369
|
-
|
370
|
-
graph.remove(name, ignore: ignore)
|
405
|
+
Berkshelf.log.debug "New lockfile:"
|
406
|
+
Berkshelf.log.debug ""
|
407
|
+
to_lock.each_line do |line|
|
408
|
+
Berkshelf.log.debug " #{line.chomp}"
|
371
409
|
end
|
410
|
+
Berkshelf.log.debug ""
|
372
411
|
end
|
373
412
|
|
374
413
|
|
@@ -566,6 +605,10 @@ module Berkshelf
|
|
566
605
|
dependency = @lockfile.find(name) ||
|
567
606
|
@berksfile && @berksfile.find(name) ||
|
568
607
|
Dependency.new(@berksfile, name)
|
608
|
+
|
609
|
+
# We need to make a copy of the dependency, or else we could be
|
610
|
+
# modifying an existing object that other processes depend on!
|
611
|
+
dependency = dependency.dup
|
569
612
|
dependency.locked_version = item.version
|
570
613
|
|
571
614
|
hash[item.name] = dependency
|
@@ -748,6 +791,11 @@ module Berkshelf
|
|
748
791
|
def add_dependency(name, constraint)
|
749
792
|
@dependencies[name.to_s] = constraint.to_s
|
750
793
|
end
|
794
|
+
|
795
|
+
# @private
|
796
|
+
def to_s
|
797
|
+
"#{name} (#{version})"
|
798
|
+
end
|
751
799
|
end
|
752
800
|
end
|
753
801
|
end
|