berkshelf 3.0.0.beta9 → 3.0.0.rc1
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/.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
|