r10k 2.2.2 → 2.3.0
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/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
|