librarian-puppet-maestrodev 0.9.7
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/.gitignore +3 -0
- data/LICENSE +20 -0
- data/README.md +187 -0
- data/bin/librarian-puppet +9 -0
- data/lib/librarian/puppet.rb +13 -0
- data/lib/librarian/puppet/cli.rb +85 -0
- data/lib/librarian/puppet/dsl.rb +16 -0
- data/lib/librarian/puppet/environment.rb +54 -0
- data/lib/librarian/puppet/extension.rb +41 -0
- data/lib/librarian/puppet/lockfile/parser.rb +53 -0
- data/lib/librarian/puppet/source.rb +4 -0
- data/lib/librarian/puppet/source/forge.rb +279 -0
- data/lib/librarian/puppet/source/git.rb +114 -0
- data/lib/librarian/puppet/source/githubtarball.rb +234 -0
- data/lib/librarian/puppet/source/local.rb +57 -0
- data/lib/librarian/puppet/source/path.rb +12 -0
- data/lib/librarian/puppet/templates/Puppetfile +10 -0
- data/lib/librarian/puppet/version.rb +5 -0
- data/vendor/librarian/CHANGELOG.md +185 -0
- data/vendor/librarian/Gemfile +6 -0
- data/vendor/librarian/MIT-LICENSE +20 -0
- data/vendor/librarian/README.md +403 -0
- data/vendor/librarian/Rakefile +34 -0
- data/vendor/librarian/bin/librarian-chef +7 -0
- data/vendor/librarian/bin/librarian-mock +7 -0
- data/vendor/librarian/config/cucumber.yaml +1 -0
- data/vendor/librarian/features/chef/cli/init.feature +11 -0
- data/vendor/librarian/features/chef/cli/install.feature +64 -0
- data/vendor/librarian/features/chef/cli/show.feature +77 -0
- data/vendor/librarian/features/chef/cli/version.feature +11 -0
- data/vendor/librarian/features/support/env.rb +9 -0
- data/vendor/librarian/lib/librarian.rb +19 -0
- data/vendor/librarian/lib/librarian/action.rb +5 -0
- data/vendor/librarian/lib/librarian/action/base.rb +24 -0
- data/vendor/librarian/lib/librarian/action/clean.rb +44 -0
- data/vendor/librarian/lib/librarian/action/ensure.rb +24 -0
- data/vendor/librarian/lib/librarian/action/install.rb +99 -0
- data/vendor/librarian/lib/librarian/action/resolve.rb +81 -0
- data/vendor/librarian/lib/librarian/action/update.rb +78 -0
- data/vendor/librarian/lib/librarian/chef.rb +1 -0
- data/vendor/librarian/lib/librarian/chef/cli.rb +48 -0
- data/vendor/librarian/lib/librarian/chef/dsl.rb +15 -0
- data/vendor/librarian/lib/librarian/chef/environment.rb +27 -0
- data/vendor/librarian/lib/librarian/chef/extension.rb +9 -0
- data/vendor/librarian/lib/librarian/chef/integration/knife.rb +42 -0
- data/vendor/librarian/lib/librarian/chef/manifest_reader.rb +59 -0
- data/vendor/librarian/lib/librarian/chef/source.rb +3 -0
- data/vendor/librarian/lib/librarian/chef/source/git.rb +25 -0
- data/vendor/librarian/lib/librarian/chef/source/local.rb +69 -0
- data/vendor/librarian/lib/librarian/chef/source/path.rb +12 -0
- data/vendor/librarian/lib/librarian/chef/source/site.rb +446 -0
- data/vendor/librarian/lib/librarian/chef/templates/Cheffile +15 -0
- data/vendor/librarian/lib/librarian/cli.rb +205 -0
- data/vendor/librarian/lib/librarian/cli/manifest_presenter.rb +79 -0
- data/vendor/librarian/lib/librarian/config.rb +7 -0
- data/vendor/librarian/lib/librarian/config/database.rb +205 -0
- data/vendor/librarian/lib/librarian/config/file_source.rb +47 -0
- data/vendor/librarian/lib/librarian/config/hash_source.rb +33 -0
- data/vendor/librarian/lib/librarian/config/source.rb +149 -0
- data/vendor/librarian/lib/librarian/dependency.rb +91 -0
- data/vendor/librarian/lib/librarian/dsl.rb +108 -0
- data/vendor/librarian/lib/librarian/dsl/receiver.rb +48 -0
- data/vendor/librarian/lib/librarian/dsl/target.rb +172 -0
- data/vendor/librarian/lib/librarian/environment.rb +134 -0
- data/vendor/librarian/lib/librarian/error.rb +4 -0
- data/vendor/librarian/lib/librarian/helpers.rb +13 -0
- data/vendor/librarian/lib/librarian/lockfile.rb +29 -0
- data/vendor/librarian/lib/librarian/lockfile/compiler.rb +66 -0
- data/vendor/librarian/lib/librarian/lockfile/parser.rb +100 -0
- data/vendor/librarian/lib/librarian/logger.rb +46 -0
- data/vendor/librarian/lib/librarian/manifest.rb +132 -0
- data/vendor/librarian/lib/librarian/manifest_set.rb +153 -0
- data/vendor/librarian/lib/librarian/mock.rb +1 -0
- data/vendor/librarian/lib/librarian/mock/cli.rb +19 -0
- data/vendor/librarian/lib/librarian/mock/dsl.rb +15 -0
- data/vendor/librarian/lib/librarian/mock/environment.rb +24 -0
- data/vendor/librarian/lib/librarian/mock/extension.rb +9 -0
- data/vendor/librarian/lib/librarian/mock/source.rb +1 -0
- data/vendor/librarian/lib/librarian/mock/source/mock.rb +97 -0
- data/vendor/librarian/lib/librarian/mock/source/mock/registry.rb +83 -0
- data/vendor/librarian/lib/librarian/resolution.rb +44 -0
- data/vendor/librarian/lib/librarian/resolver.rb +78 -0
- data/vendor/librarian/lib/librarian/resolver/implementation.rb +118 -0
- data/vendor/librarian/lib/librarian/source.rb +2 -0
- data/vendor/librarian/lib/librarian/source/git.rb +150 -0
- data/vendor/librarian/lib/librarian/source/git/repository.rb +217 -0
- data/vendor/librarian/lib/librarian/source/local.rb +61 -0
- data/vendor/librarian/lib/librarian/source/path.rb +74 -0
- data/vendor/librarian/lib/librarian/spec.rb +13 -0
- data/vendor/librarian/lib/librarian/spec_change_set.rb +173 -0
- data/vendor/librarian/lib/librarian/specfile.rb +18 -0
- data/vendor/librarian/lib/librarian/support/abstract_method.rb +21 -0
- data/vendor/librarian/lib/librarian/ui.rb +64 -0
- data/vendor/librarian/lib/librarian/version.rb +3 -0
- data/vendor/librarian/librarian.gemspec +34 -0
- data/vendor/librarian/spec/functional/chef/source/git_spec.rb +432 -0
- data/vendor/librarian/spec/functional/chef/source/site_spec.rb +215 -0
- data/vendor/librarian/spec/functional/source/git/repository_spec.rb +149 -0
- data/vendor/librarian/spec/unit/action/base_spec.rb +18 -0
- data/vendor/librarian/spec/unit/action/clean_spec.rb +102 -0
- data/vendor/librarian/spec/unit/action/ensure_spec.rb +37 -0
- data/vendor/librarian/spec/unit/action/install_spec.rb +111 -0
- data/vendor/librarian/spec/unit/config/database_spec.rb +319 -0
- data/vendor/librarian/spec/unit/dependency_spec.rb +36 -0
- data/vendor/librarian/spec/unit/dsl_spec.rb +194 -0
- data/vendor/librarian/spec/unit/environment_spec.rb +9 -0
- data/vendor/librarian/spec/unit/lockfile/parser_spec.rb +162 -0
- data/vendor/librarian/spec/unit/lockfile_spec.rb +65 -0
- data/vendor/librarian/spec/unit/manifest_set_spec.rb +202 -0
- data/vendor/librarian/spec/unit/manifest_spec.rb +36 -0
- data/vendor/librarian/spec/unit/mock/source/mock_spec.rb +22 -0
- data/vendor/librarian/spec/unit/resolver_spec.rb +192 -0
- data/vendor/librarian/spec/unit/source/git_spec.rb +29 -0
- data/vendor/librarian/spec/unit/spec_change_set_spec.rb +169 -0
- metadata +227 -0
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
module Librarian
|
|
2
|
+
module Mock
|
|
3
|
+
module Source
|
|
4
|
+
class Mock
|
|
5
|
+
class Registry
|
|
6
|
+
|
|
7
|
+
module Dsl
|
|
8
|
+
|
|
9
|
+
class Top
|
|
10
|
+
def initialize(sources)
|
|
11
|
+
@sources = sources
|
|
12
|
+
end
|
|
13
|
+
def source(name, &block)
|
|
14
|
+
@sources[name] ||= {}
|
|
15
|
+
Source.new(@sources[name]).instance_eval(&block) if block
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
class Source
|
|
20
|
+
def initialize(source)
|
|
21
|
+
@source = source
|
|
22
|
+
end
|
|
23
|
+
def spec(name, version = nil, &block)
|
|
24
|
+
@source[name] ||= []
|
|
25
|
+
unless version
|
|
26
|
+
Spec.new(@source[name]).instance_eval(&block) if block
|
|
27
|
+
else
|
|
28
|
+
Spec.new(@source[name]).version(version, &block)
|
|
29
|
+
end
|
|
30
|
+
@source[name] = @source[name].sort_by{|a| Manifest::Version.new(a[:version])}.reverse
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
class Spec
|
|
35
|
+
def initialize(spec)
|
|
36
|
+
@spec = spec
|
|
37
|
+
end
|
|
38
|
+
def version(name, &block)
|
|
39
|
+
@spec << { :version => name, :dependencies => {} }
|
|
40
|
+
Version.new(@spec.last[:dependencies]).instance_eval(&block) if block
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
class Version
|
|
45
|
+
def initialize(version)
|
|
46
|
+
@version = version
|
|
47
|
+
end
|
|
48
|
+
def dependency(name, *requirement)
|
|
49
|
+
@version[name] = requirement
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
class << self
|
|
54
|
+
def run!(sources, &block)
|
|
55
|
+
Top.new(sources).instance_eval(&block) if block
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def initialize
|
|
62
|
+
clear!
|
|
63
|
+
end
|
|
64
|
+
def clear!
|
|
65
|
+
self.sources = { }
|
|
66
|
+
end
|
|
67
|
+
def merge!(options = nil, &block)
|
|
68
|
+
clear! if options && options[:clear]
|
|
69
|
+
Dsl.run!(sources, &block) if block
|
|
70
|
+
end
|
|
71
|
+
def [](name)
|
|
72
|
+
sources[name] ||= {}
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
private
|
|
76
|
+
|
|
77
|
+
attr_accessor :sources
|
|
78
|
+
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
end
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
module Librarian
|
|
2
|
+
#
|
|
3
|
+
# Represents the output of the resolution process. Captures the declared
|
|
4
|
+
# dependencies plus the full set of resolved manifests. The sources are
|
|
5
|
+
# already known by the dependencies and by the resolved manifests, so they do
|
|
6
|
+
# not need to be captured explicitly.
|
|
7
|
+
#
|
|
8
|
+
# This representation may be produced by the resolver, may be serialized into
|
|
9
|
+
# a lockfile, and may be deserialized from a lockfile. It is expected that the
|
|
10
|
+
# lockfile is a direct representation in text of this representation, so that
|
|
11
|
+
# the serialization-deserialization process is just the identity function.
|
|
12
|
+
#
|
|
13
|
+
class Resolution
|
|
14
|
+
attr_reader :dependencies, :manifests, :manifests_index
|
|
15
|
+
|
|
16
|
+
def initialize(dependencies, manifests)
|
|
17
|
+
@dependencies, @manifests = dependencies, manifests
|
|
18
|
+
@manifests_index = build_manifests_index(manifests)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def correct?
|
|
22
|
+
manifests && manifests_consistent_with_dependencies? && manifests_internally_consistent?
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def sources
|
|
26
|
+
manifests.map{|m| m.source}.uniq
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
private
|
|
30
|
+
|
|
31
|
+
def build_manifests_index(manifests)
|
|
32
|
+
Hash[manifests.map{|m| [m.name, m]}] if manifests
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def manifests_consistent_with_dependencies?
|
|
36
|
+
ManifestSet.new(manifests).in_compliance_with?(dependencies)
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def manifests_internally_consistent?
|
|
40
|
+
ManifestSet.new(manifests).consistent?
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
end
|
|
44
|
+
end
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
require 'librarian/resolver/implementation'
|
|
2
|
+
require 'librarian/manifest_set'
|
|
3
|
+
require 'librarian/resolution'
|
|
4
|
+
|
|
5
|
+
module Librarian
|
|
6
|
+
class Resolver
|
|
7
|
+
|
|
8
|
+
attr_accessor :environment
|
|
9
|
+
private :environment=
|
|
10
|
+
|
|
11
|
+
def initialize(environment)
|
|
12
|
+
self.environment = environment
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def resolve(spec, partial_manifests = [])
|
|
16
|
+
implementation = Implementation.new(self, spec)
|
|
17
|
+
partial_manifests_index = Hash[partial_manifests.map{|m| [m.name, m]}]
|
|
18
|
+
manifests = implementation.resolve(spec.dependencies, partial_manifests_index)
|
|
19
|
+
enforce_consistency!(spec.dependencies, manifests) if manifests
|
|
20
|
+
manifests = sort(manifests) if manifests
|
|
21
|
+
Resolution.new(spec.dependencies, manifests)
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def enforce_consistency!(dependencies, manifests)
|
|
25
|
+
return if dependencies.all?{|d|
|
|
26
|
+
m = manifests[d.name]
|
|
27
|
+
m && d.satisfied_by?(m)
|
|
28
|
+
} && ManifestSet.new(manifests).consistent?
|
|
29
|
+
|
|
30
|
+
debug { "Resolver Malfunctioned!" }
|
|
31
|
+
errors = []
|
|
32
|
+
dependencies.sort_by(&:name).each do |d|
|
|
33
|
+
m = manifests[d.name]
|
|
34
|
+
if !m
|
|
35
|
+
errors << ["Depends on #{d}", "Missing!"]
|
|
36
|
+
elsif !d.satisfied_by?(m)
|
|
37
|
+
errors << ["Depends on #{d}", "Found: #{m}"]
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
unless errors.empty?
|
|
41
|
+
errors.each do |a, b|
|
|
42
|
+
debug { " #{a}" }
|
|
43
|
+
debug { " #{b}" }
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
manifests.values.sort_by(&:name).each do |manifest|
|
|
47
|
+
errors = []
|
|
48
|
+
manifest.dependencies.sort_by(&:name).each do |d|
|
|
49
|
+
m = manifests[d.name]
|
|
50
|
+
if !m
|
|
51
|
+
errors << ["Depends on: #{d}", "Missing!"]
|
|
52
|
+
elsif !d.satisfied_by?(m)
|
|
53
|
+
errors << ["Depends on: #{d}", "Found: #{m}"]
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
unless errors.empty?
|
|
57
|
+
debug { " #{manifest}" }
|
|
58
|
+
errors.each do |a, b|
|
|
59
|
+
debug { " #{a}" }
|
|
60
|
+
debug { " #{b}" }
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
raise Error, "Resolver Malfunctioned!"
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def sort(manifests)
|
|
68
|
+
ManifestSet.sort(manifests)
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
private
|
|
72
|
+
|
|
73
|
+
def debug(*args, &block)
|
|
74
|
+
environment.logger.debug(*args, &block)
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
end
|
|
78
|
+
end
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
require 'librarian/dependency'
|
|
2
|
+
|
|
3
|
+
module Librarian
|
|
4
|
+
class Resolver
|
|
5
|
+
class Implementation
|
|
6
|
+
|
|
7
|
+
attr_reader :resolver, :source, :dependency_source_map
|
|
8
|
+
|
|
9
|
+
def initialize(resolver, spec)
|
|
10
|
+
@resolver = resolver
|
|
11
|
+
@source = spec.source
|
|
12
|
+
@dependency_source_map = Hash[spec.dependencies.map{|d| [d.name, d.source]}]
|
|
13
|
+
@level = 0
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def resolve(dependencies, manifests = {})
|
|
17
|
+
dependencies += manifests.values.map { |m|
|
|
18
|
+
m.dependencies.map { |d| sourced_dependency_for(d) }
|
|
19
|
+
}.flatten(1)
|
|
20
|
+
resolution = recursive_resolve([], manifests, dependencies)
|
|
21
|
+
resolution ? resolution[1] : nil
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def sourced_dependency_for(dependency)
|
|
25
|
+
return dependency if dependency.source
|
|
26
|
+
|
|
27
|
+
s = dependency_source_map[dependency.name] || source
|
|
28
|
+
Dependency.new(dependency.name, dependency.requirement, s)
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def recursive_resolve(dependencies, manifests, queue)
|
|
32
|
+
if dependencies.empty?
|
|
33
|
+
queue.each do |dependency|
|
|
34
|
+
debug { "Scheduling #{dependency}" }
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
failure = false
|
|
38
|
+
until failure || queue.empty?
|
|
39
|
+
dependency = queue.shift
|
|
40
|
+
dependencies << dependency
|
|
41
|
+
debug { "Resolving #{dependency}" }
|
|
42
|
+
scope do
|
|
43
|
+
if manifests.key?(dependency.name)
|
|
44
|
+
unless dependency.satisfied_by?(manifests[dependency.name])
|
|
45
|
+
debug { "Conflicts with #{manifests[dependency.name]}" }
|
|
46
|
+
failure = true
|
|
47
|
+
else
|
|
48
|
+
debug { "Accords with all prior constraints" }
|
|
49
|
+
# nothing left to do
|
|
50
|
+
end
|
|
51
|
+
else
|
|
52
|
+
debug { "No known prior constraints" }
|
|
53
|
+
resolution = nil
|
|
54
|
+
related_dependencies = dependencies.select{|d| d.name == dependency.name}
|
|
55
|
+
unless dependency.manifests && dependency.manifests.first
|
|
56
|
+
debug { "No known manifests" }
|
|
57
|
+
else
|
|
58
|
+
debug { "Checking manifests" }
|
|
59
|
+
scope do
|
|
60
|
+
dependency.manifests.each do |manifest|
|
|
61
|
+
break if resolution
|
|
62
|
+
|
|
63
|
+
debug { "Checking #{manifest}" }
|
|
64
|
+
scope do
|
|
65
|
+
if related_dependencies.all?{|d| d.satisfied_by?(manifest)}
|
|
66
|
+
m = manifests.merge(dependency.name => manifest)
|
|
67
|
+
a = manifest.dependencies.map { |d| sourced_dependency_for(d) }
|
|
68
|
+
a.each do |d|
|
|
69
|
+
debug { "Scheduling #{d}" }
|
|
70
|
+
end
|
|
71
|
+
q = queue + a
|
|
72
|
+
resolution = recursive_resolve(dependencies.dup, m, q)
|
|
73
|
+
end
|
|
74
|
+
if resolution
|
|
75
|
+
debug { "Resolved #{dependency} at #{manifest}" }
|
|
76
|
+
else
|
|
77
|
+
debug { "Backtracking from #{manifest}" }
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
if resolution
|
|
83
|
+
debug { "Resolved #{dependency}" }
|
|
84
|
+
else
|
|
85
|
+
debug { "Failed to resolve #{dependency}" }
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
unless resolution
|
|
89
|
+
failure = true
|
|
90
|
+
else
|
|
91
|
+
dependencies, manifests, queue = *resolution
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
failure ? nil : [dependencies, manifests, queue]
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
private
|
|
100
|
+
|
|
101
|
+
def scope
|
|
102
|
+
@level += 1
|
|
103
|
+
yield
|
|
104
|
+
ensure
|
|
105
|
+
@level -= 1
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
def debug
|
|
109
|
+
environment.logger.debug { ' ' * @level + yield }
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
def environment
|
|
113
|
+
resolver.environment
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
end
|
|
117
|
+
end
|
|
118
|
+
end
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
require 'fileutils'
|
|
2
|
+
require 'pathname'
|
|
3
|
+
require 'digest'
|
|
4
|
+
|
|
5
|
+
require 'librarian/source/git/repository'
|
|
6
|
+
require 'librarian/source/local'
|
|
7
|
+
|
|
8
|
+
module Librarian
|
|
9
|
+
module Source
|
|
10
|
+
class Git
|
|
11
|
+
|
|
12
|
+
include Local
|
|
13
|
+
|
|
14
|
+
class << self
|
|
15
|
+
|
|
16
|
+
LOCK_NAME = 'GIT'
|
|
17
|
+
|
|
18
|
+
def lock_name
|
|
19
|
+
LOCK_NAME
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def from_lock_options(environment, options)
|
|
23
|
+
new(environment, options[:remote], options.reject{|k, v| k == :remote})
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def from_spec_args(environment, uri, options)
|
|
27
|
+
recognized_options = [:ref, :path]
|
|
28
|
+
unrecognized_options = options.keys - recognized_options
|
|
29
|
+
unrecognized_options.empty? or raise Error, "unrecognized options: #{unrecognized_options.join(", ")}"
|
|
30
|
+
|
|
31
|
+
new(environment, uri, options)
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
DEFAULTS = {
|
|
37
|
+
:ref => 'master'
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
attr_accessor :environment
|
|
41
|
+
private :environment=
|
|
42
|
+
|
|
43
|
+
attr_accessor :uri, :ref, :sha, :path
|
|
44
|
+
private :uri=, :ref=, :sha=, :path=
|
|
45
|
+
|
|
46
|
+
def initialize(environment, uri, options)
|
|
47
|
+
self.environment = environment
|
|
48
|
+
self.uri = uri
|
|
49
|
+
self.ref = options[:ref] || DEFAULTS[:ref]
|
|
50
|
+
self.sha = options[:sha]
|
|
51
|
+
self.path = options[:path]
|
|
52
|
+
|
|
53
|
+
@repository = nil
|
|
54
|
+
@repository_cache_path = nil
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def to_s
|
|
58
|
+
path ? "#{uri}##{ref}(#{path})" : "#{uri}##{ref}"
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def ==(other)
|
|
62
|
+
other &&
|
|
63
|
+
self.class == other.class &&
|
|
64
|
+
self.uri == other.uri &&
|
|
65
|
+
self.ref == other.ref &&
|
|
66
|
+
self.path == other.path &&
|
|
67
|
+
(self.sha.nil? || other.sha.nil? || self.sha == other.sha)
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def to_spec_args
|
|
71
|
+
options = {}
|
|
72
|
+
options.merge!(:ref => ref) if ref != DEFAULTS[:ref]
|
|
73
|
+
options.merge!(:path => path) if path
|
|
74
|
+
[uri, options]
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
def to_lock_options
|
|
78
|
+
options = {:remote => uri, :ref => ref, :sha => sha}
|
|
79
|
+
options.merge!(:path => path) if path
|
|
80
|
+
options
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
def pinned?
|
|
84
|
+
!!sha
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
def unpin!
|
|
88
|
+
@sha = nil
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
def cache!
|
|
92
|
+
repository_cached? and return or repository_cached!
|
|
93
|
+
|
|
94
|
+
unless repository.git?
|
|
95
|
+
repository.path.rmtree if repository.path.exist?
|
|
96
|
+
repository.path.mkpath
|
|
97
|
+
repository.clone!(uri)
|
|
98
|
+
end
|
|
99
|
+
repository.reset_hard!
|
|
100
|
+
repository.clean!
|
|
101
|
+
unless repository.checked_out?(sha)
|
|
102
|
+
remote = repository.default_remote
|
|
103
|
+
repository.fetch!(remote)
|
|
104
|
+
repository.fetch!(remote, :tags => true)
|
|
105
|
+
|
|
106
|
+
self.sha = repository.hash_from(remote, ref) unless sha
|
|
107
|
+
repository.checkout!(sha) unless repository.checked_out?(sha)
|
|
108
|
+
|
|
109
|
+
raise Error, "failed to checkout #{sha}" unless repository.checked_out?(sha)
|
|
110
|
+
end
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
private
|
|
114
|
+
|
|
115
|
+
attr_accessor :repository_cached
|
|
116
|
+
alias repository_cached? repository_cached
|
|
117
|
+
|
|
118
|
+
def repository_cached!
|
|
119
|
+
self.repository_cached = true
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
def repository_cache_path
|
|
123
|
+
@repository_cache_path ||= begin
|
|
124
|
+
environment.cache_path.join("source/git/#{cache_key}")
|
|
125
|
+
end
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
def repository
|
|
129
|
+
@repository ||= begin
|
|
130
|
+
Repository.new(environment, repository_cache_path)
|
|
131
|
+
end
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
def filesystem_path
|
|
135
|
+
@filesystem_path ||= path ? repository.path.join(path) : repository.path
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
def cache_key
|
|
139
|
+
@cache_key ||= begin
|
|
140
|
+
uri_part = uri
|
|
141
|
+
path_part = "/#{path}" if path
|
|
142
|
+
ref_part = "##{ref}"
|
|
143
|
+
key_source = [uri_part, path_part, ref_part].join
|
|
144
|
+
Digest::MD5.hexdigest(key_source)
|
|
145
|
+
end
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
end
|
|
149
|
+
end
|
|
150
|
+
end
|