r10k 1.1.4 → 1.2.0rc1
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 +8 -8
- data/.gitignore +1 -0
- data/.nodeset.yml +7 -0
- data/.rspec +1 -0
- data/.travis.yml +2 -1
- data/CHANGELOG +17 -12
- data/Gemfile +8 -0
- data/README.markdown +4 -2
- data/Rakefile +1 -0
- data/doc/dynamic-environments.markdown +206 -0
- data/doc/puppetfile.markdown +87 -0
- data/lib/r10k/cli.rb +1 -1
- data/lib/r10k/errors.rb +30 -3
- data/lib/r10k/execution.rb +5 -2
- data/lib/r10k/git/cache.rb +26 -42
- data/lib/r10k/git/commit.rb +22 -0
- data/lib/r10k/git/errors.rb +31 -22
- data/lib/r10k/git/head.rb +33 -0
- data/lib/r10k/git/ref.rb +63 -0
- data/lib/r10k/git/repository.rb +65 -36
- data/lib/r10k/git/tag.rb +26 -0
- data/lib/r10k/git/working_dir.rb +93 -83
- data/lib/r10k/git.rb +14 -0
- data/lib/r10k/module/forge.rb +129 -62
- data/lib/r10k/module/git.rb +72 -6
- data/lib/r10k/module/metadata.rb +47 -0
- data/lib/r10k/module/svn.rb +99 -0
- data/lib/r10k/module.rb +1 -0
- data/lib/r10k/module_repository/forge.rb +64 -0
- data/lib/r10k/module_repository.rb +8 -0
- data/lib/r10k/semver.rb +1 -1
- data/lib/r10k/svn/working_dir.rb +76 -0
- data/lib/r10k/task/deployment.rb +21 -28
- data/lib/r10k/util/subprocess/io.rb +12 -0
- data/lib/r10k/util/subprocess/result.rb +36 -0
- data/lib/r10k/util/subprocess/runner.rb +88 -0
- data/lib/r10k/util/subprocess.rb +107 -0
- data/lib/r10k/version.rb +1 -1
- data/r10k.gemspec +11 -1
- data/spec/fixtures/vcr/cassettes/R10K_ModuleRepository_Forge/and_the_expected_version_is_latest/can_fetch_all_versions_of_a_given_module.yml +42 -0
- data/spec/fixtures/vcr/cassettes/R10K_ModuleRepository_Forge/and_the_expected_version_is_latest/can_fetch_the_latest_version_of_a_given_module.yml +42 -0
- data/spec/fixtures/vcr/cassettes/R10K_ModuleRepository_Forge/looking_up_versions/can_fetch_all_versions_of_a_given_module.yml +42 -0
- data/spec/fixtures/vcr/cassettes/R10K_ModuleRepository_Forge/looking_up_versions/can_fetch_the_latest_version_of_a_given_module.yml +42 -0
- data/spec/fixtures/vcr/cassettes/R10K_ModuleRepository_Forge/looking_up_versions.yml +42 -0
- data/spec/fixtures/vcr/cassettes/R10K_Module_Forge/and_the_expected_version_is_latest/sets_the_expected_version_based_on_the_latest_forge_version.yml +42 -0
- data/spec/rspec-system-r10k/puppetfile.rb +24 -0
- data/spec/rspec-system-r10k/tmpdir.rb +32 -0
- data/spec/shared-examples/git-ref.rb +49 -0
- data/spec/spec_helper.rb +23 -0
- data/spec/system/module/forge/install_spec.rb +51 -0
- data/spec/system/module/git/install_spec.rb +117 -0
- data/spec/system/module/svn/install_spec.rb +51 -0
- data/spec/system/module/svn/update_spec.rb +38 -0
- data/spec/system/spec_helper.rb +60 -0
- data/spec/system/system-helpers.rb +4 -0
- data/spec/system/version_spec.rb +7 -0
- data/spec/system-provisioning/el.rb +38 -0
- data/spec/unit/deployment/source_spec.rb +1 -1
- data/spec/unit/git/cache_spec.rb +38 -0
- data/spec/unit/git/commit_spec.rb +33 -0
- data/spec/unit/git/head_spec.rb +27 -0
- data/spec/unit/git/ref_spec.rb +68 -0
- data/spec/unit/git/tag_spec.rb +31 -0
- data/spec/unit/module/forge_spec.rb +157 -37
- data/spec/unit/module/git_spec.rb +49 -0
- data/spec/unit/module/metadata_spec.rb +68 -0
- data/spec/unit/module/svn_spec.rb +146 -0
- data/spec/unit/module_repository/forge_spec.rb +32 -0
- metadata +151 -8
data/lib/r10k/execution.rb
CHANGED
@@ -13,6 +13,7 @@ module Execution
|
|
13
13
|
# @params [Hash] opts
|
14
14
|
#
|
15
15
|
# @option opts [String] :event An optional log event name. Defaults to cmd.
|
16
|
+
# @option opts [String] :cwd The working directory to use when executing the command
|
16
17
|
#
|
17
18
|
# @raise [R10K::ExecutionFailure] If the executed command exited with a
|
18
19
|
# nonzero exit code.
|
@@ -20,11 +21,13 @@ module Execution
|
|
20
21
|
# @return [String] the stdout from the command
|
21
22
|
def execute(cmd, opts = {})
|
22
23
|
|
23
|
-
|
24
|
+
logger.warn "R10K::Execution#execute is deprecated, use R10K::Util::Subprocess"
|
25
|
+
|
26
|
+
event = (opts.delete(:event) || cmd)
|
24
27
|
|
25
28
|
logger.debug1 "Execute: #{event.inspect}"
|
26
29
|
|
27
|
-
status, stdout, stderr = systemu(cmd)
|
30
|
+
status, stdout, stderr = systemu(cmd, opts)
|
28
31
|
|
29
32
|
logger.debug2 "[#{event}] STDOUT: #{stdout.chomp}" unless stdout.empty?
|
30
33
|
logger.debug2 "[#{event}] STDERR: #{stderr.chomp}" unless stderr.empty?
|
data/lib/r10k/git/cache.rb
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
require 'r10k/logging'
|
2
|
+
|
3
|
+
require 'r10k/git'
|
2
4
|
require 'r10k/git/repository'
|
3
5
|
|
4
6
|
require 'r10k/settings'
|
5
7
|
require 'r10k/registry'
|
6
8
|
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
#
|
12
|
-
# @see man git-clone(1)
|
9
|
+
# Mirror a git repository for use shared git object repositories
|
10
|
+
#
|
11
|
+
# @see man git-clone(1)
|
12
|
+
class R10K::Git::Cache < R10K::Git::Repository
|
13
13
|
|
14
14
|
include R10K::Settings::Mixin
|
15
15
|
|
@@ -25,28 +25,24 @@ class Cache < R10K::Git::Repository
|
|
25
25
|
|
26
26
|
include R10K::Logging
|
27
27
|
|
28
|
-
# @!attribute [r] remote
|
29
|
-
# @return [String] The git repository remote
|
30
|
-
attr_reader :remote
|
31
|
-
|
32
28
|
# @!attribute [r] path
|
29
|
+
# @deprecated
|
33
30
|
# @return [String] The path to the git cache repository
|
34
|
-
|
31
|
+
def path
|
32
|
+
logger.warn "#{self.class}#path is deprecated; use #git_dir"
|
33
|
+
@git_dir
|
34
|
+
end
|
35
35
|
|
36
36
|
# @param [String] remote
|
37
37
|
# @param [String] cache_root
|
38
38
|
def initialize(remote)
|
39
39
|
@remote = remote
|
40
40
|
|
41
|
-
@
|
41
|
+
@git_dir = File.join(settings[:cache_root], sanitized_dirname)
|
42
42
|
end
|
43
43
|
|
44
44
|
def sync
|
45
|
-
if @synced
|
46
|
-
# XXX This gets really spammy. Might be good to turn it on later, but for
|
47
|
-
# general work it's way much.
|
48
|
-
#logger.debug "#{@remote} already synced this run, not syncing again"
|
49
|
-
else
|
45
|
+
if not @synced
|
50
46
|
sync!
|
51
47
|
@synced = true
|
52
48
|
end
|
@@ -54,41 +50,35 @@ class Cache < R10K::Git::Repository
|
|
54
50
|
|
55
51
|
def sync!
|
56
52
|
if cached?
|
57
|
-
|
58
|
-
# general work it's way much.
|
59
|
-
#logger.debug "Updating existing cache at #{@path}"
|
60
|
-
git "fetch --prune", :git_dir => @path
|
53
|
+
fetch
|
61
54
|
else
|
62
55
|
logger.debug "Creating new git cache for #{@remote.inspect}"
|
63
56
|
|
57
|
+
# TODO extract this to an initialization step
|
64
58
|
unless File.exist? settings[:cache_root]
|
65
59
|
FileUtils.mkdir_p settings[:cache_root]
|
66
60
|
end
|
67
61
|
|
68
|
-
git
|
62
|
+
git ['clone', '--mirror', @remote, git_dir]
|
63
|
+
end
|
64
|
+
rescue R10K::Util::Subprocess::SubprocessError => e
|
65
|
+
msg = e.result.stderr.slice(/^fatal: .*$/)
|
66
|
+
if msg
|
67
|
+
raise R10K::Git::GitError, "Couldn't update git cache for #{@remote}: #{msg.inspect}"
|
68
|
+
else
|
69
|
+
raise e
|
69
70
|
end
|
70
71
|
end
|
71
72
|
|
72
73
|
# @return [Array<String>] A list the branches for the git repository
|
73
74
|
def branches
|
74
|
-
output = git
|
75
|
-
output.
|
76
|
-
# the `git branch` command returns output like this:
|
77
|
-
# <pre>
|
78
|
-
# 0.11.x
|
79
|
-
# 0.12.x
|
80
|
-
# * master
|
81
|
-
# passenger_scoping
|
82
|
-
# </pre>
|
83
|
-
#
|
84
|
-
# The string index notation strips off the leading whitespace/asterisk
|
85
|
-
str[2..-1]
|
86
|
-
end
|
75
|
+
output = git %w[for-each-ref refs/heads --format %(refname)], :git_dir => git_dir
|
76
|
+
output.scan(%r[refs/heads/(.*)$]).flatten
|
87
77
|
end
|
88
78
|
|
89
79
|
# @return [true, false] If the repository has been locally cached
|
90
80
|
def cached?
|
91
|
-
File.exist?
|
81
|
+
File.exist? git_dir
|
92
82
|
end
|
93
83
|
|
94
84
|
private
|
@@ -97,10 +87,4 @@ class Cache < R10K::Git::Repository
|
|
97
87
|
def sanitized_dirname
|
98
88
|
@remote.gsub(/[^@\w\.-]/, '-')
|
99
89
|
end
|
100
|
-
|
101
|
-
def git_dir
|
102
|
-
@path
|
103
|
-
end
|
104
|
-
end
|
105
|
-
end
|
106
90
|
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'r10k/git/ref'
|
2
|
+
require 'r10k/git/repository'
|
3
|
+
|
4
|
+
# commit: A 40-byte hex representation of a SHA1 referencing a specific commit
|
5
|
+
# @see https://www.kernel.org/pub/software/scm/git/docs/gitglossary.html
|
6
|
+
# @api private
|
7
|
+
class R10K::Git::Commit < R10K::Git::Ref
|
8
|
+
|
9
|
+
# @!attribute [r] commit
|
10
|
+
# @return [String] The git commit
|
11
|
+
attr_reader :commit
|
12
|
+
alias :ref :commit
|
13
|
+
|
14
|
+
def initialize(commit, repository = nil)
|
15
|
+
@commit = commit
|
16
|
+
@repository = repository
|
17
|
+
end
|
18
|
+
|
19
|
+
def fetch?
|
20
|
+
! resolvable?
|
21
|
+
end
|
22
|
+
end
|
data/lib/r10k/git/errors.rb
CHANGED
@@ -1,34 +1,43 @@
|
|
1
|
+
require 'r10k/errors'
|
2
|
+
|
1
3
|
module R10K
|
2
|
-
module Git
|
3
|
-
class NonexistentHashError < StandardError
|
4
|
-
# Raised when a hash was requested that can't be found in the repository
|
4
|
+
module Git
|
5
5
|
|
6
|
-
|
7
|
-
|
6
|
+
class GitError < R10KError
|
7
|
+
end
|
8
8
|
|
9
|
-
|
10
|
-
super(msg)
|
9
|
+
class UnresolvableRefError < GitError
|
11
10
|
|
12
|
-
|
13
|
-
|
11
|
+
attr_reader :ref
|
12
|
+
attr_reader :git_dir
|
14
13
|
|
15
|
-
|
14
|
+
def initialize(*args)
|
15
|
+
super
|
16
16
|
|
17
|
-
|
18
|
-
|
19
|
-
msg = super
|
20
|
-
if msg and msg.match(HASHLIKE)
|
21
|
-
msg = "Could not locate hash #{msg.inspect} in repository"
|
22
|
-
elsif msg.nil?
|
23
|
-
msg = "Could not locate hash in repository"
|
17
|
+
@hash = @options[:ref]
|
18
|
+
@git_dir = @options[:git_dir]
|
24
19
|
end
|
25
20
|
|
26
|
-
|
27
|
-
|
28
|
-
|
21
|
+
HASHLIKE = %r[[A-Fa-f0-9]]
|
22
|
+
|
23
|
+
# Print a friendly error message if an object hash is given as the message
|
24
|
+
def message
|
25
|
+
if @mesg
|
26
|
+
msg = @mesg
|
27
|
+
else
|
28
|
+
msg = "Could not locate hash"
|
29
29
|
|
30
|
-
|
30
|
+
if @hash
|
31
|
+
msg << " '#{@hash}'"
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
if @git_dir
|
36
|
+
msg << " at #{@git_dir}"
|
37
|
+
end
|
38
|
+
|
39
|
+
msg
|
40
|
+
end
|
31
41
|
end
|
32
42
|
end
|
33
43
|
end
|
34
|
-
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'r10k/git'
|
2
|
+
require 'r10k/git/ref'
|
3
|
+
require 'r10k/git/repository'
|
4
|
+
|
5
|
+
|
6
|
+
# head: A named reference to the commit at the tip of a branch. Heads are
|
7
|
+
# stored in a file in $GIT_DIR/refs/heads/ directory. except when using packed
|
8
|
+
#
|
9
|
+
# @see https://www.kernel.org/pub/software/scm/git/docs/gitglossary.html
|
10
|
+
# @api private
|
11
|
+
class R10K::Git::Head < R10K::Git::Ref
|
12
|
+
|
13
|
+
# @!attribute [r] head
|
14
|
+
# @return [String] The git head
|
15
|
+
attr_reader :head
|
16
|
+
alias :ref :head
|
17
|
+
|
18
|
+
def initialize(head, repository = nil)
|
19
|
+
@head = head
|
20
|
+
@repository = repository
|
21
|
+
end
|
22
|
+
|
23
|
+
# def sha1
|
24
|
+
# TODO ensure that @head is an actual head as opposed to a tag or other
|
25
|
+
# hooliganism.
|
26
|
+
#end
|
27
|
+
|
28
|
+
# If we are tracking a branch, we should always try to fetch a newer version
|
29
|
+
# of that branch.
|
30
|
+
def fetch?
|
31
|
+
true
|
32
|
+
end
|
33
|
+
end
|
data/lib/r10k/git/ref.rb
ADDED
@@ -0,0 +1,63 @@
|
|
1
|
+
require 'r10k/git'
|
2
|
+
require 'r10k/git/repository'
|
3
|
+
|
4
|
+
# ref: A 40-byte hex representation of a SHA1 or a name that denotes a
|
5
|
+
# particular object. They may be stored in a file under $GIT_DIR/refs/
|
6
|
+
# directory, or in the $GIT_DIR/packed-refs file.
|
7
|
+
#
|
8
|
+
# @see https://www.kernel.org/pub/software/scm/git/docs/gitglossary.html
|
9
|
+
# @api private
|
10
|
+
class R10K::Git::Ref
|
11
|
+
|
12
|
+
# @!attribute [r] ref
|
13
|
+
# @return [String] The git reference
|
14
|
+
attr_reader :ref
|
15
|
+
|
16
|
+
# @!attribute [rw] repository
|
17
|
+
# @return [R10K::Git::Repository] A git repository that can be used to
|
18
|
+
# resolve the git reference to a commit.
|
19
|
+
attr_accessor :repository
|
20
|
+
|
21
|
+
def initialize(ref, repository = nil)
|
22
|
+
@ref = ref
|
23
|
+
@repository = repository
|
24
|
+
end
|
25
|
+
|
26
|
+
# Can we locate the commit in the related repository?
|
27
|
+
def resolvable?
|
28
|
+
sha1
|
29
|
+
true
|
30
|
+
rescue R10K::Git::UnresolvableRefError
|
31
|
+
false
|
32
|
+
end
|
33
|
+
|
34
|
+
# Should we try to fetch this ref?
|
35
|
+
#
|
36
|
+
# Since we don't know the type of this ref, we have to assume that it might
|
37
|
+
# be a branch and always update accordingly.
|
38
|
+
def fetch?
|
39
|
+
true
|
40
|
+
end
|
41
|
+
|
42
|
+
def sha1
|
43
|
+
if @repository.nil?
|
44
|
+
raise ArgumentError, "Cannot resolve #{self.inspect}: no associated git repository"
|
45
|
+
else
|
46
|
+
@repository.rev_parse(ref)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def ==(other)
|
51
|
+
other.sha1 == self.sha1
|
52
|
+
rescue ArgumentError, R10K::Git::UnresolvableRefError
|
53
|
+
false
|
54
|
+
end
|
55
|
+
|
56
|
+
def to_s
|
57
|
+
ref
|
58
|
+
end
|
59
|
+
|
60
|
+
def inspect
|
61
|
+
"#<#{self.class}: #{to_s}>"
|
62
|
+
end
|
63
|
+
end
|
data/lib/r10k/git/repository.rb
CHANGED
@@ -1,74 +1,103 @@
|
|
1
|
-
require 'r10k/
|
2
|
-
require 'r10k/
|
1
|
+
require 'r10k/git'
|
2
|
+
require 'r10k/util/subprocess'
|
3
3
|
|
4
|
-
|
5
|
-
|
6
|
-
class Repository
|
7
|
-
# Define an abstract base class for git repositories.
|
8
|
-
|
9
|
-
include R10K::Execution
|
4
|
+
# Define an abstract base class for git repositories.
|
5
|
+
class R10K::Git::Repository
|
10
6
|
|
11
7
|
# @!attribute [r] remote
|
12
8
|
# @return [String] The URL to the git repository
|
13
9
|
attr_reader :remote
|
14
10
|
|
15
11
|
# @!attribute [r] basedir
|
16
|
-
# @return [String] The
|
12
|
+
# @return [String] The directory containing the repository
|
17
13
|
attr_reader :basedir
|
18
14
|
|
19
15
|
# @!attribute [r] dirname
|
20
|
-
# @return [String] The name
|
16
|
+
# @return [String] The name of the directory
|
21
17
|
attr_reader :dirname
|
22
18
|
|
23
|
-
#
|
19
|
+
# @!attribute [r] git_dir
|
20
|
+
# Set the path to the git directory. For git repositories with working copies
|
21
|
+
# this will be `$working_dir/.git`; for bare repositories this will be
|
22
|
+
# `bare-repo.git`
|
23
|
+
# @return [String] The path to the git directory
|
24
|
+
attr_reader :git_dir
|
25
|
+
|
26
|
+
# Resolve a ref to a git commit. The given pattern can be a commit, tag,
|
27
|
+
# or a local or remote branch
|
28
|
+
#
|
29
|
+
# @param [String] pattern
|
24
30
|
#
|
25
|
-
# @
|
31
|
+
# @return [String] The dereferenced hash of `pattern`
|
32
|
+
def resolve_ref(pattern)
|
33
|
+
commit = nil
|
34
|
+
begin
|
35
|
+
all_commits = git ['show-ref', '-s', pattern], :git_dir => git_dir
|
36
|
+
commit = all_commits.lines.first
|
37
|
+
rescue R10K::Util::Subprocess::SubprocessError
|
38
|
+
end
|
39
|
+
|
40
|
+
if commit.nil?
|
41
|
+
begin
|
42
|
+
commit = git ['rev-parse', "#{ref}^{commit}"], :git_dir => git_dir
|
43
|
+
rescue R10K::Util::Subprocess::SubprocessError
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
if commit
|
48
|
+
commit.chomp
|
49
|
+
else
|
50
|
+
raise R10K::Git::UnresolvableRefError.new(:ref => pattern, :git_dir => git_dir)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
alias rev_parse resolve_ref
|
54
|
+
|
55
|
+
private
|
56
|
+
|
57
|
+
# Fetch objects and refs from the given git remote
|
26
58
|
#
|
27
|
-
# @
|
28
|
-
def
|
29
|
-
|
30
|
-
commit.chomp
|
31
|
-
rescue R10K::ExecutionFailure
|
32
|
-
raise R10K::Git::NonexistentHashError.new(ref, git_dir)
|
59
|
+
# @param remote [#to_s] The remote name to fetch from
|
60
|
+
def fetch(remote = 'origin')
|
61
|
+
git ['fetch', '--prune', remote], :git_dir => @git_dir
|
33
62
|
end
|
34
63
|
|
35
64
|
# Wrap git commands
|
36
65
|
#
|
37
|
-
# @param [String]
|
38
|
-
# @param [Hash] opts
|
66
|
+
# @param cmd [Array<String>] cmd The arguments for the git prompt
|
67
|
+
# @param opts [Hash] opts
|
39
68
|
#
|
69
|
+
# @option opts [String] :path
|
40
70
|
# @option opts [String] :git_dir
|
41
71
|
# @option opts [String] :work_tree
|
42
|
-
# @option opts [String] :work_tree
|
43
72
|
#
|
44
73
|
# @raise [R10K::ExecutionFailure] If the executed command exited with a
|
45
74
|
# nonzero exit code.
|
46
75
|
#
|
47
76
|
# @return [String] The git command output
|
48
|
-
def git(
|
49
|
-
|
50
|
-
|
51
|
-
log_event = "git #{command_line_args}"
|
52
|
-
log_event << ", args: #{opts.inspect}" unless opts.empty?
|
53
|
-
|
77
|
+
def git(cmd, opts = {})
|
78
|
+
argv = %w{git}
|
54
79
|
|
55
80
|
if opts[:path]
|
56
|
-
|
57
|
-
|
81
|
+
argv << "--git-dir" << File.join(opts[:path], '.git')
|
82
|
+
argv << "--work-tree" << opts[:path]
|
58
83
|
else
|
59
84
|
if opts[:git_dir]
|
60
|
-
|
85
|
+
argv << "--git-dir" << opts[:git_dir]
|
61
86
|
end
|
62
87
|
if opts[:work_tree]
|
63
|
-
|
88
|
+
argv << "--work-tree" << opts[:work_tree]
|
64
89
|
end
|
65
90
|
end
|
66
91
|
|
67
|
-
|
68
|
-
|
92
|
+
argv.concat(cmd)
|
93
|
+
|
94
|
+
subproc = R10K::Util::Subprocess.new(argv)
|
95
|
+
subproc.raise_on_fail = true
|
96
|
+
subproc.logger = self.logger
|
97
|
+
|
98
|
+
result = subproc.execute
|
69
99
|
|
70
|
-
|
100
|
+
# todo ensure that logging always occurs even if the command fails to run
|
101
|
+
result.stdout
|
71
102
|
end
|
72
103
|
end
|
73
|
-
end
|
74
|
-
end
|