r10k 2.2.2 → 2.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.mkd +25 -0
- data/Gemfile +1 -1
- data/doc/dynamic-environments/configuration.mkd +36 -11
- data/integration/tests/basic_functionality/proxy_with_pe_only_module.rb +128 -0
- data/lib/r10k/errors.rb +18 -0
- data/lib/r10k/forge/module_release.rb +3 -3
- data/lib/r10k/git.rb +53 -0
- data/lib/r10k/git/rugged/bare_repository.rb +16 -7
- data/lib/r10k/git/rugged/base_repository.rb +16 -2
- data/lib/r10k/git/rugged/credentials.rb +9 -0
- data/lib/r10k/git/rugged/working_repository.rb +18 -5
- data/lib/r10k/git/shellgit/bare_repository.rb +12 -3
- data/lib/r10k/git/shellgit/base_repository.rb +19 -3
- data/lib/r10k/git/shellgit/working_repository.rb +13 -3
- data/lib/r10k/initializers.rb +1 -0
- data/lib/r10k/settings.rb +41 -22
- data/lib/r10k/settings/collection.rb +25 -21
- data/lib/r10k/settings/definition.rb +14 -2
- data/lib/r10k/settings/helpers.rb +38 -0
- data/lib/r10k/settings/list.rb +107 -0
- data/lib/r10k/util/symbolize_keys.rb +6 -2
- data/lib/r10k/version.rb +1 -1
- data/r10k.gemspec +1 -1
- data/r10k.yaml.example +38 -12
- data/spec/shared-examples/git/bare_repository.rb +62 -0
- data/spec/shared-examples/git/working_repository.rb +57 -11
- data/spec/shared-examples/settings/ancestry.rb +44 -0
- data/spec/unit/forge/module_release_spec.rb +1 -1
- data/spec/unit/git/rugged/credentials_spec.rb +6 -0
- data/spec/unit/settings/collection_spec.rb +2 -1
- data/spec/unit/settings/definition_spec.rb +6 -5
- data/spec/unit/settings/inheritance_spec.rb +38 -0
- data/spec/unit/settings/list_spec.rb +88 -0
- data/spec/unit/settings_spec.rb +52 -23
- data/spec/unit/util/attempt_spec.rb +1 -1
- data/spec/unit/util/symbolize_keys_spec.rb +25 -9
- metadata +11 -4
@@ -36,7 +36,12 @@ class R10K::Git::Rugged::WorkingRepository < R10K::Git::Rugged::BaseRepository
|
|
36
36
|
# alternate object database.
|
37
37
|
options = {:credentials => credentials}
|
38
38
|
options.merge!(:alternates => [File.join(opts[:reference], 'objects')]) if opts[:reference]
|
39
|
-
|
39
|
+
|
40
|
+
proxy = R10K::Git.get_proxy_for_remote(remote)
|
41
|
+
|
42
|
+
R10K::Git.with_proxy(proxy) do
|
43
|
+
@_rugged_repo = ::Rugged::Repository.clone_at(remote, @path.to_s, options)
|
44
|
+
end
|
40
45
|
|
41
46
|
if opts[:reference]
|
42
47
|
alternates << File.join(opts[:reference], 'objects')
|
@@ -70,11 +75,19 @@ class R10K::Git::Rugged::WorkingRepository < R10K::Git::Rugged::BaseRepository
|
|
70
75
|
end
|
71
76
|
end
|
72
77
|
|
73
|
-
def fetch(
|
74
|
-
logger.debug1 { "Fetching remote '#{
|
78
|
+
def fetch(remote_name = 'origin')
|
79
|
+
logger.debug1 { "Fetching remote '#{remote_name}' at #{@path}" }
|
75
80
|
options = {:credentials => credentials}
|
76
|
-
refspecs = ["+refs/heads/*:refs/remotes/#{
|
77
|
-
|
81
|
+
refspecs = ["+refs/heads/*:refs/remotes/#{remote_name}/*"]
|
82
|
+
|
83
|
+
remote = remotes[remote_name]
|
84
|
+
proxy = R10K::Git.get_proxy_for_remote(remote)
|
85
|
+
results = nil
|
86
|
+
|
87
|
+
R10K::Git.with_proxy(proxy) do
|
88
|
+
results = with_repo { |repo| repo.fetch(remote_name, refspecs, options) }
|
89
|
+
end
|
90
|
+
|
78
91
|
report_transfer(results, remote)
|
79
92
|
rescue Rugged::SshError, Rugged::NetworkError => e
|
80
93
|
raise R10K::Git::GitError.new(e.message, :git_dir => git_dir, :backtrace => e.backtrace)
|
@@ -21,11 +21,20 @@ class R10K::Git::ShellGit::BareRepository < R10K::Git::ShellGit::BaseRepository
|
|
21
21
|
end
|
22
22
|
|
23
23
|
def clone(remote)
|
24
|
-
|
24
|
+
proxy = R10K::Git.get_proxy_for_remote(remote)
|
25
|
+
|
26
|
+
R10K::Git.with_proxy(proxy) do
|
27
|
+
git ['clone', '--mirror', remote, git_dir.to_s]
|
28
|
+
end
|
25
29
|
end
|
26
30
|
|
27
|
-
def fetch
|
28
|
-
|
31
|
+
def fetch(remote_name='origin')
|
32
|
+
remote = remotes[remote_name]
|
33
|
+
proxy = R10K::Git.get_proxy_for_remote(remote)
|
34
|
+
|
35
|
+
R10K::Git.with_proxy(proxy) do
|
36
|
+
git ['fetch', remote_name, '--prune'], :git_dir => git_dir.to_s
|
37
|
+
end
|
29
38
|
end
|
30
39
|
|
31
40
|
def exist?
|
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'r10k/git/shellgit'
|
2
|
+
require 'r10k/util/subprocess'
|
2
3
|
require 'r10k/logging'
|
3
4
|
|
4
5
|
class R10K::Git::ShellGit::BaseRepository
|
@@ -47,6 +48,23 @@ class R10K::Git::ShellGit::BaseRepository
|
|
47
48
|
end
|
48
49
|
end
|
49
50
|
|
51
|
+
# @return [Hash] Collection of remotes for this repo, keys are the remote name and values are the remote URL.
|
52
|
+
def remotes
|
53
|
+
result = git ['config', '--local', '--get-regexp', '^remote\..*\.url$'], :git_dir => git_dir.to_s, :raise_on_fail => false
|
54
|
+
|
55
|
+
if result.success?
|
56
|
+
Hash[
|
57
|
+
result.stdout.split("\n").collect do |remote|
|
58
|
+
matches = /^remote\.(.*)\.url (.*)$/.match(remote)
|
59
|
+
|
60
|
+
[matches[1], matches[2]]
|
61
|
+
end
|
62
|
+
]
|
63
|
+
else
|
64
|
+
{}
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
50
68
|
include R10K::Logging
|
51
69
|
|
52
70
|
private
|
@@ -95,8 +113,6 @@ class R10K::Git::ShellGit::BaseRepository
|
|
95
113
|
subproc.raise_on_fail = raise_on_fail
|
96
114
|
subproc.logger = self.logger
|
97
115
|
|
98
|
-
|
99
|
-
|
100
|
-
result
|
116
|
+
subproc.execute
|
101
117
|
end
|
102
118
|
end
|
@@ -32,7 +32,12 @@ class R10K::Git::ShellGit::WorkingRepository < R10K::Git::ShellGit::BaseReposito
|
|
32
32
|
if opts[:reference]
|
33
33
|
argv += ['--reference', opts[:reference]]
|
34
34
|
end
|
35
|
-
|
35
|
+
|
36
|
+
proxy = R10K::Git.get_proxy_for_remote(remote)
|
37
|
+
|
38
|
+
R10K::Git.with_proxy(proxy) do
|
39
|
+
git argv
|
40
|
+
end
|
36
41
|
|
37
42
|
if opts[:ref]
|
38
43
|
checkout(opts[:ref])
|
@@ -46,8 +51,13 @@ class R10K::Git::ShellGit::WorkingRepository < R10K::Git::ShellGit::BaseReposito
|
|
46
51
|
git ['checkout', ref], :path => @path.to_s
|
47
52
|
end
|
48
53
|
|
49
|
-
def fetch
|
50
|
-
|
54
|
+
def fetch(remote_name='origin')
|
55
|
+
remote = remotes[remote_name]
|
56
|
+
proxy = R10K::Git.get_proxy_for_remote(remote)
|
57
|
+
|
58
|
+
R10K::Git.with_proxy(proxy) do
|
59
|
+
git ['fetch', remote_name, '--prune'], :path => @path.to_s
|
60
|
+
end
|
51
61
|
end
|
52
62
|
|
53
63
|
def exist?
|
data/lib/r10k/initializers.rb
CHANGED
@@ -42,6 +42,7 @@ module R10K
|
|
42
42
|
with_setting(:provider) { |value| R10K::Git.provider = value }
|
43
43
|
with_setting(:username) { |value| R10K::Git.settings[:username] = value }
|
44
44
|
with_setting(:private_key) { |value| R10K::Git.settings[:private_key] = value }
|
45
|
+
with_setting(:proxy) { |value| R10K::Git.settings[:proxy] = value }
|
45
46
|
with_setting(:repositories) { |value| R10K::Git.settings[:repositories] = value }
|
46
47
|
end
|
47
48
|
end
|
data/lib/r10k/settings.rb
CHANGED
@@ -7,6 +7,7 @@ module R10K
|
|
7
7
|
|
8
8
|
require 'r10k/settings/collection'
|
9
9
|
require 'r10k/settings/definition'
|
10
|
+
require 'r10k/settings/list'
|
10
11
|
|
11
12
|
def self.git_settings
|
12
13
|
R10K::Settings::Collection.new(:git, [
|
@@ -29,20 +30,33 @@ module R10K
|
|
29
30
|
Only used by the 'rugged' Git provider.",
|
30
31
|
}),
|
31
32
|
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
33
|
+
URIDefinition.new(:proxy, {
|
34
|
+
:desc => "An optional proxy server to use when interacting with Git sources via HTTP(S).",
|
35
|
+
:default => :inherit,
|
36
|
+
}),
|
37
|
+
|
38
|
+
List.new(:repositories, lambda {
|
39
|
+
R10K::Settings::Collection.new(nil, [
|
40
|
+
Definition.new(:remote, {
|
41
|
+
:desc => "Remote source that repository-specific settings should apply to.",
|
42
|
+
}),
|
43
|
+
|
44
|
+
Definition.new(:private_key, {
|
45
|
+
:desc => "The path to the SSH private key for Git SSH remotes.
|
46
|
+
Only used by the 'rugged' Git provider.",
|
47
|
+
:default => :inherit,
|
48
|
+
}),
|
49
|
+
|
50
|
+
URIDefinition.new(:proxy, {
|
51
|
+
:desc => "An optional proxy server to use when interacting with Git sources via HTTP(S).",
|
52
|
+
:default => :inherit,
|
53
|
+
}),
|
54
|
+
])
|
55
|
+
},
|
56
|
+
{
|
57
|
+
:desc => "Repository specific configuration.",
|
58
|
+
:default => [],
|
59
|
+
}),
|
46
60
|
])
|
47
61
|
end
|
48
62
|
|
@@ -50,14 +64,7 @@ module R10K
|
|
50
64
|
R10K::Settings::Collection.new(:forge, [
|
51
65
|
URIDefinition.new(:proxy, {
|
52
66
|
:desc => "An optional proxy server to use when downloading modules from the forge.",
|
53
|
-
:default =>
|
54
|
-
[
|
55
|
-
ENV['HTTPS_PROXY'],
|
56
|
-
ENV['https_proxy'],
|
57
|
-
ENV['HTTP_PROXY'],
|
58
|
-
ENV['http_proxy']
|
59
|
-
].find { |value| value }
|
60
|
-
end
|
67
|
+
:default => :inherit,
|
61
68
|
}),
|
62
69
|
|
63
70
|
URIDefinition.new(:baseurl, {
|
@@ -104,6 +111,18 @@ module R10K
|
|
104
111
|
end
|
105
112
|
}),
|
106
113
|
|
114
|
+
URIDefinition.new(:proxy, {
|
115
|
+
:desc => "Proxy to use for all r10k operations which occur over HTTP(S).",
|
116
|
+
:default => lambda {
|
117
|
+
[
|
118
|
+
ENV['HTTPS_PROXY'],
|
119
|
+
ENV['https_proxy'],
|
120
|
+
ENV['HTTP_PROXY'],
|
121
|
+
ENV['http_proxy']
|
122
|
+
].find { |value| value }
|
123
|
+
},
|
124
|
+
}),
|
125
|
+
|
107
126
|
R10K::Settings.forge_settings,
|
108
127
|
|
109
128
|
R10K::Settings.git_settings,
|
@@ -1,3 +1,4 @@
|
|
1
|
+
require 'r10k/settings/helpers'
|
1
2
|
require 'r10k/settings/definition'
|
2
3
|
require 'r10k/util/setopts'
|
3
4
|
require 'r10k/util/symbolize_keys'
|
@@ -9,6 +10,7 @@ module R10K
|
|
9
10
|
# Define a group of settings, which can be single definitions or nested
|
10
11
|
# collections.
|
11
12
|
class Collection
|
13
|
+
include R10K::Settings::Helpers
|
12
14
|
|
13
15
|
# @!attribute [r] name
|
14
16
|
# @return [String] The name of this collection
|
@@ -18,7 +20,14 @@ module R10K
|
|
18
20
|
# @param settings [Array] All settings in this collection
|
19
21
|
def initialize(name, settings)
|
20
22
|
@name = name
|
21
|
-
|
23
|
+
|
24
|
+
@settings = {}
|
25
|
+
|
26
|
+
# iterate through settings and adopt them
|
27
|
+
settings.each do |s|
|
28
|
+
s.parent = self
|
29
|
+
@settings[s.name] = s
|
30
|
+
end
|
22
31
|
end
|
23
32
|
|
24
33
|
# Assign new values, perform validation checks, and return the final
|
@@ -39,8 +48,8 @@ module R10K
|
|
39
48
|
def assign(newvalues)
|
40
49
|
return if newvalues.nil?
|
41
50
|
|
42
|
-
# TODO: this results in inconsistency for hashes inside arrays.
|
43
51
|
R10K::Util::SymbolizeKeys.symbolize_keys!(newvalues)
|
52
|
+
|
44
53
|
@settings.each_pair do |name, setting|
|
45
54
|
if newvalues.key?(name)
|
46
55
|
setting.assign(newvalues[name])
|
@@ -64,7 +73,13 @@ module R10K
|
|
64
73
|
end
|
65
74
|
|
66
75
|
if !errors.empty?
|
67
|
-
|
76
|
+
if @name
|
77
|
+
msg = "Validation failed for '#{@name}' settings group"
|
78
|
+
else
|
79
|
+
msg = "Validation failed for settings group"
|
80
|
+
end
|
81
|
+
|
82
|
+
raise ValidationError.new(msg, :errors => errors)
|
68
83
|
end
|
69
84
|
end
|
70
85
|
|
@@ -72,12 +87,19 @@ module R10K
|
|
72
87
|
# @return [Hash]
|
73
88
|
def resolve
|
74
89
|
rv = {}
|
90
|
+
|
75
91
|
@settings.each_pair do |name, setting|
|
76
92
|
rv[name] = setting.resolve
|
77
93
|
end
|
94
|
+
|
78
95
|
rv.freeze
|
79
96
|
end
|
80
97
|
|
98
|
+
# Access individual settings via a Hash-like interface.
|
99
|
+
def [](name)
|
100
|
+
@settings[name]
|
101
|
+
end
|
102
|
+
|
81
103
|
class ValidationError < R10K::Error
|
82
104
|
|
83
105
|
attr_reader :errors
|
@@ -95,24 +117,6 @@ module R10K
|
|
95
117
|
end
|
96
118
|
struct.join("\n")
|
97
119
|
end
|
98
|
-
|
99
|
-
private
|
100
|
-
|
101
|
-
def structure_exception(name, exc)
|
102
|
-
struct = []
|
103
|
-
struct << "#{name}:"
|
104
|
-
if exc.is_a? ValidationError
|
105
|
-
struct << indent(exc.format)
|
106
|
-
else
|
107
|
-
struct << indent(exc.message)
|
108
|
-
end
|
109
|
-
struct.join("\n")
|
110
|
-
end
|
111
|
-
|
112
|
-
def indent(str, level = 4)
|
113
|
-
prefix = ' ' * level
|
114
|
-
str.gsub(/^/, prefix)
|
115
|
-
end
|
116
120
|
end
|
117
121
|
end
|
118
122
|
end
|
@@ -1,3 +1,4 @@
|
|
1
|
+
require 'r10k/settings/helpers'
|
1
2
|
require 'r10k/util/setopts'
|
2
3
|
|
3
4
|
module R10K
|
@@ -6,10 +7,10 @@ module R10K
|
|
6
7
|
# Define a single setting and additional attributes like descriptions,
|
7
8
|
# default values, and validation.
|
8
9
|
class Definition
|
9
|
-
|
10
10
|
require 'r10k/settings/uri_definition'
|
11
11
|
require 'r10k/settings/enum_definition'
|
12
12
|
|
13
|
+
include R10K::Settings::Helpers
|
13
14
|
include R10K::Util::Setopts
|
14
15
|
|
15
16
|
# @!attribute [r] name
|
@@ -90,7 +91,18 @@ module R10K
|
|
90
91
|
if !@value.nil?
|
91
92
|
@value
|
92
93
|
elsif @default
|
93
|
-
@default
|
94
|
+
if @default == :inherit
|
95
|
+
# walk all the way up to root, starting with grandparent
|
96
|
+
ancestor = parent
|
97
|
+
|
98
|
+
while ancestor = ancestor.parent
|
99
|
+
return ancestor[@name].resolve if ancestor.respond_to?(:[]) && ancestor[@name]
|
100
|
+
end
|
101
|
+
elsif @default.is_a?(Proc)
|
102
|
+
@default.call
|
103
|
+
else
|
104
|
+
@default
|
105
|
+
end
|
94
106
|
end
|
95
107
|
end
|
96
108
|
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require 'r10k/errors'
|
2
|
+
require 'r10k/settings/collection'
|
3
|
+
|
4
|
+
module R10K
|
5
|
+
module Settings
|
6
|
+
module Helpers
|
7
|
+
def self.included(klass)
|
8
|
+
klass.send(:include, InstanceMethods)
|
9
|
+
klass.send(:extend, ClassMethods)
|
10
|
+
end
|
11
|
+
|
12
|
+
module InstanceMethods
|
13
|
+
# Assign a parent collection to this setting. Parent may only be
|
14
|
+
# assigned once.
|
15
|
+
#
|
16
|
+
# @param new_parent [R10K::Settings::Collection] Parent collection
|
17
|
+
def parent=(new_parent)
|
18
|
+
unless @parent.nil?
|
19
|
+
raise R10K::Error.new("#{self.class} instances cannot be reassigned to a new parent.")
|
20
|
+
end
|
21
|
+
|
22
|
+
unless new_parent.is_a?(R10K::Settings::Collection) || new_parent.is_a?(R10K::Settings::List)
|
23
|
+
raise R10K::Error.new("#{self.class} instances may only belong to a settings collection or list.")
|
24
|
+
end
|
25
|
+
|
26
|
+
@parent = new_parent
|
27
|
+
end
|
28
|
+
|
29
|
+
def parent
|
30
|
+
@parent
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
module ClassMethods
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,107 @@
|
|
1
|
+
require 'r10k/settings/helpers'
|
2
|
+
require 'r10k/settings/collection'
|
3
|
+
require 'r10k/errors'
|
4
|
+
require 'r10k/util/setopts'
|
5
|
+
|
6
|
+
module R10K
|
7
|
+
module Settings
|
8
|
+
|
9
|
+
# A container for an arbitrarily long list of other settings.
|
10
|
+
class List
|
11
|
+
include R10K::Settings::Helpers
|
12
|
+
include R10K::Util::Setopts
|
13
|
+
|
14
|
+
# @!attribute [r] name
|
15
|
+
# @return [String] The name of this collection
|
16
|
+
attr_reader :name
|
17
|
+
|
18
|
+
# @param name [Symbol] The name of the setting for this definition.
|
19
|
+
# @param item_proc [#call] An object whose #call method will return a
|
20
|
+
# new instance of another R10K::Settings class to hold each item
|
21
|
+
# added to this list.
|
22
|
+
# @param opts [Hash] Additional options for this definition to control
|
23
|
+
# validation, normalization, and the like.
|
24
|
+
#
|
25
|
+
# @options opts [String] :desc Extended description of this setting.
|
26
|
+
# @options opts [Array] :default Initial/default contents of the list.
|
27
|
+
def initialize(name, item_proc, opts = {})
|
28
|
+
@name = name
|
29
|
+
@item_proc = item_proc
|
30
|
+
@items = []
|
31
|
+
|
32
|
+
setopts(opts, allowed_initialize_opts)
|
33
|
+
end
|
34
|
+
|
35
|
+
# Takes an array of key/value pairs and assigns each into a
|
36
|
+
# new instance created by invoking @item_proc.
|
37
|
+
#
|
38
|
+
# @param items [Array] List of items to add to this list.
|
39
|
+
def assign(items)
|
40
|
+
return if items.nil?
|
41
|
+
|
42
|
+
items.each do |values|
|
43
|
+
new_item = @item_proc.call
|
44
|
+
new_item.parent = self
|
45
|
+
new_item.assign(values)
|
46
|
+
@items << new_item
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
# Validate all items in the list and return validation errors
|
51
|
+
#
|
52
|
+
# @return [nil, Hash] If all validation passed nil will be returned; if
|
53
|
+
# validation failed then a hash of those errors will be returned.
|
54
|
+
def validate
|
55
|
+
errors = {}
|
56
|
+
|
57
|
+
@items.each_with_index do |item, idx|
|
58
|
+
begin
|
59
|
+
item.validate
|
60
|
+
rescue => error
|
61
|
+
errors[idx+1] = error
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
if !errors.empty?
|
66
|
+
raise ValidationError.new("Validation failed for '#{@name}' settings list", :errors => errors)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
# Evaluate all items in the list and return a frozen array of the final values.
|
71
|
+
# @return [Array]
|
72
|
+
def resolve
|
73
|
+
@items.collect { |item| item.resolve }.freeze
|
74
|
+
end
|
75
|
+
|
76
|
+
class ValidationError < R10K::Error
|
77
|
+
attr_reader :errors
|
78
|
+
|
79
|
+
def initialize(mesg, options = {})
|
80
|
+
super
|
81
|
+
@errors = options[:errors]
|
82
|
+
end
|
83
|
+
|
84
|
+
def format
|
85
|
+
struct = []
|
86
|
+
struct << "#{message}:"
|
87
|
+
@errors.each do |item, error|
|
88
|
+
struct << indent(structure_exception("Item #{item}", error))
|
89
|
+
end
|
90
|
+
struct.join("\n")
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
private
|
95
|
+
|
96
|
+
# Subclasses may define additional params that are accepted at
|
97
|
+
# initialization; they should override this method to add any
|
98
|
+
# additional fields that should be respected.
|
99
|
+
def allowed_initialize_opts
|
100
|
+
{
|
101
|
+
:desc => true,
|
102
|
+
:default => true,
|
103
|
+
}
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|