puppet-library 0.9.1 → 0.10.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -7
- data/CHANGELOG.yml +1 -0
- data/README.md +9 -4
- data/Rakefile +44 -23
- data/TODO.yml +3 -4
- data/config.ru +28 -3
- data/lib/puppet_library/forge/cache.rb +19 -0
- data/lib/puppet_library/forge/directory.rb +16 -0
- data/lib/puppet_library/forge/git_repository.rb +57 -49
- data/lib/puppet_library/forge/proxy.rb +18 -4
- data/lib/puppet_library/forge/source.rb +10 -0
- data/lib/puppet_library/puppet_library.rb +1 -1
- data/lib/puppet_library/server.rb +12 -3
- data/lib/puppet_library/util/git.rb +103 -0
- data/lib/puppet_library/util/patches.rb +104 -0
- data/lib/puppet_library/util/temp_dir.rb +42 -0
- data/lib/puppet_library/util.rb +4 -70
- data/lib/puppet_library/version.rb +1 -1
- data/spec/archive/archive_reader_spec.rb +9 -2
- data/spec/archive/archiver_spec.rb +4 -0
- data/spec/forge/cache_spec.rb +4 -0
- data/spec/forge/directory_spec.rb +4 -0
- data/spec/forge/git_repository_spec.rb +5 -2
- data/spec/forge/source_spec.rb +4 -0
- data/spec/integration_test_helper.rb +42 -0
- data/spec/util/git_spec.rb +143 -0
- data/spec/util/patches_spec.rb +86 -0
- data/spec/util/temp_dir_spec.rb +35 -0
- data/test/directory_forge_integration_test.rb +96 -0
- data/test/offline_git_repo_forge_integration_test.rb +122 -0
- data/test/offline_proxy_forge_integration_test.rb +126 -0
- data/test/online_git_repo_forge_integration_test.rb +89 -0
- data/test/online_proxy_forge_integration_test.rb +93 -0
- data/test/source_forge_integration_test.rb +96 -0
- metadata +292 -118
- data/spec/util_spec.rb +0 -43
- data/test/librarian_puppet_integration_test.rb +0 -349
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
|
-
---
|
2
|
-
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
5
|
-
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: e4ad4f98c15d6ba4b89830bb6f30c72dc2ce3efd
|
4
|
+
data.tar.gz: 487e711b4ecdea363118803048f8320a902ed6e2
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 11bb00e50d4037bb7e14c60e69fe8c5d99e5f032dd4cb76adaa670462df40c62b7fe230488b2747fa730c685b88315560bb9543dff3698ef81894e4262ace257
|
7
|
+
data.tar.gz: 986c55e4faa32246bc1c9387180fec9488b2c153caed62038328f10a5af4b78180880f007e548e6fe0f48bd8e597b04c89a5d48eb3753c754c08855ae04eddc4
|
data/CHANGELOG.yml
CHANGED
data/README.md
CHANGED
@@ -146,11 +146,16 @@ require "rubygems"
|
|
146
146
|
require "puppet_library"
|
147
147
|
|
148
148
|
# NB: this config API is not yet stable, and may change without notice
|
149
|
-
server = PuppetLibrary::Server.
|
149
|
+
server = PuppetLibrary::Server.configure do |library|
|
150
150
|
# Serve our private modules
|
151
|
-
library.forge PuppetLibrary::Forge::Directory
|
152
|
-
|
153
|
-
|
151
|
+
library.forge PuppetLibrary::Forge::Directory do |forge|
|
152
|
+
forge.path = "/var/lib/modules"
|
153
|
+
end
|
154
|
+
|
155
|
+
# Download all other modules from the Puppet Forge
|
156
|
+
library.forge PuppetLibrary::Forge::Proxy do |forge|
|
157
|
+
forge.url = "http://forge.puppetlabs.com"
|
158
|
+
end
|
154
159
|
end
|
155
160
|
|
156
161
|
run server
|
data/Rakefile
CHANGED
@@ -17,7 +17,6 @@
|
|
17
17
|
|
18
18
|
require 'bundler/gem_tasks'
|
19
19
|
require 'rspec/core/rake_task'
|
20
|
-
require 'coveralls/rake/task'
|
21
20
|
require 'json'
|
22
21
|
require 'yaml'
|
23
22
|
require 'net/http'
|
@@ -61,7 +60,16 @@ rescue
|
|
61
60
|
return true
|
62
61
|
end
|
63
62
|
|
64
|
-
|
63
|
+
if RUBY_VERSION.start_with? "1.8"
|
64
|
+
namespace :coveralls do
|
65
|
+
task :push do
|
66
|
+
puts "Skipping Coverage pushing because this Ruby version doesn't support it"
|
67
|
+
end
|
68
|
+
end
|
69
|
+
else
|
70
|
+
require 'coveralls/rake/task'
|
71
|
+
Coveralls::RakeTask.new
|
72
|
+
end
|
65
73
|
|
66
74
|
desc "Run the specs"
|
67
75
|
RSpec::Core::RakeTask.new(:spec)
|
@@ -102,7 +110,7 @@ end
|
|
102
110
|
task :default => [:test, 'coveralls:push']
|
103
111
|
|
104
112
|
desc "Check it works on all local rubies"
|
105
|
-
task :verify => 'test-imports' do
|
113
|
+
task :verify => [ 'check-license', 'test-imports' ] do
|
106
114
|
versions = SUPPORTED_RUBY_VERSIONS
|
107
115
|
puts "\nRunning Specs".green
|
108
116
|
spec_results = versions.map do |ruby_version|
|
@@ -122,13 +130,18 @@ task :verify => 'test-imports' do
|
|
122
130
|
system "rvm #{ruby_version} do bundle exec rake features"
|
123
131
|
end
|
124
132
|
|
133
|
+
gem_versions = versions.map do |ruby_version|
|
134
|
+
`rvm #{ruby_version} do gem --version`.strip
|
135
|
+
end
|
136
|
+
|
125
137
|
puts "\nResults:\n".green
|
126
|
-
results = [ spec_results, integration_test_results, acceptance_test_results ].transpose
|
127
|
-
puts "
|
128
|
-
puts "| Version | Specs | ITs | ATs |"
|
129
|
-
puts "
|
130
|
-
versions.zip(results).each do |(version, (spec_result, integration_test_result, acceptance_test_result))|
|
138
|
+
results = [ gem_versions, spec_results, integration_test_results, acceptance_test_results ].transpose
|
139
|
+
puts "+---------+----------+-------+-------+-------+"
|
140
|
+
puts "| Version | Gem Ver. | Specs | ITs | ATs |"
|
141
|
+
puts "+---------+----------+-------+-------+-------+"
|
142
|
+
versions.zip(results).each do |(version, (gem_version, spec_result, integration_test_result, acceptance_test_result))|
|
131
143
|
v = version.ljust(7)
|
144
|
+
g = gem_version.ljust(8)
|
132
145
|
s = spec_result ? "pass".green : "fail".red
|
133
146
|
if ruby_version_supports_integration_test? version
|
134
147
|
i = integration_test_result ? "pass".green : "fail".red
|
@@ -141,35 +154,44 @@ task :verify => 'test-imports' do
|
|
141
154
|
else
|
142
155
|
a = "skip".yellow
|
143
156
|
end
|
144
|
-
puts "| #{v} | #{s} | #{i} | #{a} |"
|
157
|
+
puts "| #{v} | #{g} | #{s} | #{i} | #{a} |"
|
145
158
|
end
|
146
|
-
puts "
|
159
|
+
puts "+---------+----------+-------+-------+-------+"
|
147
160
|
|
148
|
-
versions.zip(results).each do |(version, (spec_result, integration_test_result))|
|
161
|
+
versions.zip(results).each do |(version, (gem_version, spec_result, integration_test_result, acceptance_test_result))|
|
149
162
|
unless spec_result
|
150
163
|
fail "Specs failed with Ruby #{version}"
|
151
164
|
end
|
152
165
|
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
166
|
+
unless integration_test_result
|
167
|
+
fail "Integration tests failed with Ruby #{version}"
|
168
|
+
end
|
169
|
+
|
170
|
+
unless acceptance_test_result
|
171
|
+
fail "Acceptance tests failed with Ruby #{version}"
|
157
172
|
end
|
158
173
|
end
|
159
174
|
end
|
160
175
|
|
176
|
+
desc "Run simple checks"
|
177
|
+
task :check => [ "check-license", "test-imports" ]do
|
178
|
+
end
|
179
|
+
|
161
180
|
desc "Check all files for license headers"
|
162
181
|
task "check-license" do
|
163
|
-
|
182
|
+
print "Checking that all program files contain license headers"
|
164
183
|
|
165
184
|
files = `git ls-files`.split "\n"
|
166
185
|
ignored_files = File.read(".licenseignore").split("\n") << ".licenseignore"
|
167
186
|
offending_files = files.reject { |file| File.read(file).include? "WITHOUT ANY WARRANTY" } - ignored_files
|
168
|
-
|
169
|
-
|
187
|
+
ok = offending_files.empty?
|
188
|
+
result = if ok
|
189
|
+
"OK".green
|
170
190
|
else
|
171
|
-
|
191
|
+
"FAIL".red
|
172
192
|
end
|
193
|
+
puts " [ #{result} ]"
|
194
|
+
abort("ERROR: THE FOLLOWING FILES HAVE NO LICENSE HEADERS: \n" + offending_files.join("\n")) unless ok
|
173
195
|
end
|
174
196
|
|
175
197
|
desc "Print the version number"
|
@@ -200,8 +222,7 @@ end
|
|
200
222
|
|
201
223
|
desc "Import files individually to make sure they can be imported externally"
|
202
224
|
task "test-imports" do
|
203
|
-
puts "Testing imports"
|
204
|
-
puts
|
225
|
+
puts "Testing imports:"
|
205
226
|
Dir.chdir "lib"
|
206
227
|
|
207
228
|
paths = Dir["**/*.rb"].map {|f| f.sub /\.rb$/, "" }
|
@@ -209,7 +230,7 @@ task "test-imports" do
|
|
209
230
|
errors = []
|
210
231
|
paths.each do |path|
|
211
232
|
print "importing #{path}..."
|
212
|
-
output = `ruby -e '$LOAD_PATH.unshift(File.expand_path(".")); require "#{path}"' 2>&1`
|
233
|
+
output = `bundle exec ruby -e '$LOAD_PATH.unshift(File.expand_path(".")); require "#{path}"' 2>&1`
|
213
234
|
print " ["
|
214
235
|
if $?.success?
|
215
236
|
print "OK".green
|
@@ -243,7 +264,7 @@ def upload_release_notes(version)
|
|
243
264
|
end
|
244
265
|
|
245
266
|
tag = "v#{version}"
|
246
|
-
changelog = YAML.load_file("CHANGELOG.yml")
|
267
|
+
changelog = YAML.load_file(File.expand_path("CHANGELOG.yml", File.dirname(__FILE__)))
|
247
268
|
release_notes = changelog.find {|release| release["tag"] == tag}
|
248
269
|
changes = release_notes ? release_notes["changes"] : []
|
249
270
|
description = changes.map { |change| "- #{change}" }.join("\n")
|
data/TODO.yml
CHANGED
@@ -2,9 +2,6 @@ features:
|
|
2
2
|
- Web UI:
|
3
3
|
- asynchronous (index page loads too slowly)
|
4
4
|
- Proxy a git repository:
|
5
|
-
- make it threadsafe (checkouts into temp dirs)
|
6
|
-
- make the specs fast
|
7
|
-
- add an integration test
|
8
5
|
- make it work with remote forges (clone and fetch on query/download)
|
9
6
|
- make it fast (pre-clone repos on startup (maybe just warn if they can't be found). Maybe cache artifacts?)
|
10
7
|
- logging
|
@@ -15,7 +12,9 @@ features:
|
|
15
12
|
- clear proxy cache (web form and API)
|
16
13
|
- delete modules from disk (web form)
|
17
14
|
- Authentication
|
18
|
-
-
|
15
|
+
- Config APIs:
|
16
|
+
- parameterless blocks (especially for Server. Include PuppetLibrary::Forge aliased to Forge in scope)
|
17
|
+
- validation of required params
|
19
18
|
|
20
19
|
dubious_features:
|
21
20
|
- Proxy modules' source in a directory (supported individually for now: should we just leave it that way?)
|
data/config.ru
CHANGED
@@ -18,9 +18,34 @@
|
|
18
18
|
require 'rubygems'
|
19
19
|
require 'puppet_library'
|
20
20
|
|
21
|
-
server = PuppetLibrary::Server.
|
22
|
-
|
23
|
-
|
21
|
+
server = PuppetLibrary::Server.configure do |library|
|
22
|
+
Forge = PuppetLibrary::Forge
|
23
|
+
|
24
|
+
# My custom modules
|
25
|
+
library.forge Forge::Directory do |forge|
|
26
|
+
forge.path = "/var/lib/modules"
|
27
|
+
end
|
28
|
+
|
29
|
+
# Unreleased versions from Github
|
30
|
+
library.forge Forge::GitRepository do |forge|
|
31
|
+
forge.repository = "https://github.com/puppetlabs/puppetlabs-apache.git"
|
32
|
+
forge.tag_regex = /[0-9.]+/
|
33
|
+
end
|
34
|
+
|
35
|
+
library.forge Forge::GitRepository do |forge|
|
36
|
+
forge.repository = "https://github.com/puppetlabs/puppetlabs-concat.git"
|
37
|
+
forge.tag_regex = /[0-9.]+/
|
38
|
+
end
|
39
|
+
|
40
|
+
library.forge Forge::GitRepository do |forge|
|
41
|
+
forge.repository = "https://github.com/puppetlabs/puppetlabs-stdlib.git"
|
42
|
+
forge.tag_regex = /[0-9.]+/
|
43
|
+
end
|
44
|
+
|
45
|
+
# Everything from The Forge
|
46
|
+
library.forge Forge::Proxy do |forge|
|
47
|
+
forge.url = "http://forge.puppetlabs.com"
|
48
|
+
end
|
24
49
|
end
|
25
50
|
|
26
51
|
run server
|
@@ -21,7 +21,26 @@ module PuppetLibrary::Forge
|
|
21
21
|
|
22
22
|
# A forge that proxies a remote forge. All module archives downloaded from the
|
23
23
|
# remote forged are cached to disk.
|
24
|
+
#
|
25
|
+
# <b>Usage:</b>
|
26
|
+
#
|
27
|
+
# forge = PuppetLibrary::Forge::Cache.configure do |repo|
|
28
|
+
# # The URL of the remote forge
|
29
|
+
# repo.url = "http://forge.example.com
|
30
|
+
#
|
31
|
+
# # The path to cache the files to on disk
|
32
|
+
# repo.path = "/var/modules/cache
|
33
|
+
# end
|
24
34
|
class Cache < Proxy
|
35
|
+
class Config
|
36
|
+
attr_accessor :url, :path
|
37
|
+
end
|
38
|
+
|
39
|
+
def self.configure
|
40
|
+
config = Config.new
|
41
|
+
yield(config)
|
42
|
+
Cache.new(config.url, config.path)
|
43
|
+
end
|
25
44
|
|
26
45
|
# * <tt>:url</tt> - The URL of the remote forge.
|
27
46
|
# * <tt>:cache_dir</tt> - The directory in which to cache the downloaded artifacts.
|
@@ -27,7 +27,23 @@ module PuppetLibrary::Forge
|
|
27
27
|
# * The modules must be named in the format <tt>author-modulename-version.tar.gz</tt>
|
28
28
|
# * The modules must contain a +metadata.json+ file
|
29
29
|
# That is, the format must be the same as what is produced by <tt>puppet module build</tt>
|
30
|
+
#
|
31
|
+
# <b>Usage:</b>
|
32
|
+
#
|
33
|
+
# forge = PuppetLibrary::Forge::Directory.configure do |repo|
|
34
|
+
# # The path to serve the modules from
|
35
|
+
# repo.path = "/var/modules/cache
|
36
|
+
# end
|
30
37
|
class Directory < PuppetLibrary::Forge::Abstract
|
38
|
+
class Config
|
39
|
+
attr_accessor :path
|
40
|
+
end
|
41
|
+
|
42
|
+
def self.configure
|
43
|
+
config = Config.new
|
44
|
+
yield(config)
|
45
|
+
Directory.new(config.path)
|
46
|
+
end
|
31
47
|
|
32
48
|
# * <tt>:module_dir</tt> - The directory containing the packaged modules.
|
33
49
|
def initialize(module_dir)
|
@@ -15,92 +15,100 @@
|
|
15
15
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
16
16
|
|
17
17
|
require 'json'
|
18
|
-
require 'rubygems/package'
|
19
18
|
require 'zlib'
|
19
|
+
require 'open3'
|
20
|
+
require 'rubygems/package'
|
20
21
|
require 'puppet_library/forge/abstract'
|
22
|
+
require 'puppet_library/util/git'
|
23
|
+
require 'puppet_library/util/temp_dir'
|
21
24
|
|
22
25
|
module PuppetLibrary::Forge
|
26
|
+
# A forge for serving modules from a Git repository
|
27
|
+
#
|
28
|
+
# <b>Usage:</b>
|
29
|
+
#
|
30
|
+
# forge = PuppetLibrary::Forge::GitRepository.configure do |repo|
|
31
|
+
# # The location of the git repository
|
32
|
+
# repo.source = "http://example.com/mymodule.git
|
33
|
+
#
|
34
|
+
# # A regular expression describing which tags to serve
|
35
|
+
# repo.include_tags = /[0-9.]+/
|
36
|
+
# end
|
23
37
|
class GitRepository < PuppetLibrary::Forge::Abstract
|
24
|
-
|
38
|
+
class Config
|
39
|
+
attr_accessor :source
|
40
|
+
attr_accessor :include_tags
|
41
|
+
end
|
42
|
+
|
43
|
+
def self.configure
|
44
|
+
config = Config.new
|
45
|
+
yield(config)
|
46
|
+
GitRepository.new(config.source, config.include_tags)
|
47
|
+
end
|
48
|
+
|
49
|
+
# * <tt>:source</tt> - The URL or path of the git repository
|
50
|
+
# * <tt>:version_tag_regex</tt> - A regex that describes which tags to serve
|
51
|
+
def initialize(source, version_tag_regex)
|
25
52
|
super(self)
|
26
|
-
|
27
|
-
@name = name
|
28
|
-
@path = File.expand_path(git_path)
|
53
|
+
cache_path = PuppetLibrary::Util::TempDir.create("git-repo-cache")
|
29
54
|
@version_tag_regex = version_tag_regex
|
55
|
+
@git = PuppetLibrary::Util::Git.new(source, cache_path)
|
56
|
+
end
|
57
|
+
|
58
|
+
def destroy!
|
59
|
+
@git.clear_cache!
|
30
60
|
end
|
31
61
|
|
32
62
|
def get_module(author, name, version)
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
unless
|
37
|
-
|
38
|
-
end
|
63
|
+
return nil unless tags.include? tag_for(version)
|
64
|
+
|
65
|
+
metadata = modulefile_for(version).to_metadata
|
66
|
+
return nil unless metadata["name"] == "#{author}-#{name}"
|
67
|
+
|
39
68
|
on_tag_for(version) do
|
40
|
-
PuppetLibrary::Archive::Archiver.archive_dir(
|
69
|
+
PuppetLibrary::Archive::Archiver.archive_dir('.', "#{metadata["name"]}-#{version}") do |archive|
|
41
70
|
archive.add_file("metadata.json", 0644) do |entry|
|
42
|
-
entry.write
|
71
|
+
entry.write metadata.to_json
|
43
72
|
end
|
44
73
|
end
|
45
74
|
end
|
46
75
|
end
|
47
76
|
|
48
|
-
def
|
49
|
-
unless author == @author && module_name == @name
|
50
|
-
return []
|
51
|
-
end
|
77
|
+
def get_all_metadata
|
52
78
|
tags.map do |tag|
|
53
79
|
modulefile_for_tag(tag).to_metadata
|
54
80
|
end
|
55
81
|
end
|
56
82
|
|
57
|
-
def
|
58
|
-
|
83
|
+
def get_metadata(author, module_name)
|
84
|
+
metadata = get_all_metadata
|
85
|
+
metadata.select do |m|
|
86
|
+
m["author"] == author
|
87
|
+
m["name"] == "#{author}-#{module_name}"
|
88
|
+
end
|
59
89
|
end
|
60
90
|
|
61
91
|
private
|
92
|
+
|
62
93
|
def tags
|
63
|
-
git
|
94
|
+
@git.tags.select {|tag| tag =~ @version_tag_regex }
|
64
95
|
end
|
65
96
|
|
66
97
|
def modulefile_for_tag(tag)
|
67
|
-
modulefile_source = git("
|
98
|
+
modulefile_source = @git.read_file("Modulefile", tag)
|
68
99
|
PuppetLibrary::PuppetModule::Modulefile.parse(modulefile_source)
|
69
100
|
end
|
70
101
|
|
71
|
-
def
|
72
|
-
|
73
|
-
PuppetLibrary::PuppetModule::Modulefile.read(modulefile_path)
|
74
|
-
end
|
75
|
-
|
76
|
-
def package_name(version)
|
77
|
-
"#{@author}-#{@name}-#{version}.tar.gz"
|
78
|
-
end
|
79
|
-
|
80
|
-
def tag_name(version)
|
81
|
-
version
|
102
|
+
def modulefile_for(version)
|
103
|
+
modulefile_for_tag(tag_for(version))
|
82
104
|
end
|
83
105
|
|
84
106
|
def on_tag_for(version, &block)
|
85
|
-
on_tag(
|
86
|
-
end
|
87
|
-
|
88
|
-
def on_tag(tag, &block)
|
89
|
-
git "checkout #{tag}"
|
90
|
-
in_dir(@path, &block)
|
107
|
+
@git.on_tag(tag_for(version), &block)
|
91
108
|
end
|
92
109
|
|
93
|
-
def
|
94
|
-
|
95
|
-
Dir.chdir dir
|
96
|
-
yield
|
97
|
-
ensure
|
98
|
-
Dir.chdir origin
|
99
|
-
end
|
100
|
-
|
101
|
-
def git(command)
|
102
|
-
#TODO: redirection will fail on windows. How do we properly discard stderr?
|
103
|
-
IO.popen("git --git-dir=#{@path}/.git --work-tree=#{@path} #{command} 2>/dev/null").read
|
110
|
+
def tag_for(version)
|
111
|
+
version
|
104
112
|
end
|
105
113
|
end
|
106
114
|
end
|
@@ -22,13 +22,27 @@ require 'puppet_library/http/cache/noop'
|
|
22
22
|
module PuppetLibrary::Forge
|
23
23
|
|
24
24
|
# A forge that proxies a remote forge.
|
25
|
+
#
|
26
|
+
# <b>Usage:</b>
|
27
|
+
#
|
28
|
+
# forge = PuppetLibrary::Forge::Proxy.configure do |repo|
|
29
|
+
# # The URL of the remote forge
|
30
|
+
# repo.url = "http://forge.example.com
|
31
|
+
# end
|
25
32
|
class Proxy
|
26
33
|
|
34
|
+
class Config
|
35
|
+
attr_accessor :url
|
36
|
+
end
|
37
|
+
|
38
|
+
def self.configure
|
39
|
+
config = Config.new
|
40
|
+
yield(config)
|
41
|
+
Proxy.new(config.url)
|
42
|
+
end
|
43
|
+
|
27
44
|
# * <tt>:url</tt> - The URL of the remote forge.
|
28
|
-
def initialize(url,
|
29
|
-
query_cache = PuppetLibrary::Http::Cache::InMemory.new,
|
30
|
-
download_cache = PuppetLibrary::Http::Cache::NoOp.new,
|
31
|
-
http_client = PuppetLibrary::Http::HttpClient.new)
|
45
|
+
def initialize(url, query_cache = PuppetLibrary::Http::Cache::InMemory.new, download_cache = PuppetLibrary::Http::Cache::NoOp.new, http_client = PuppetLibrary::Http::HttpClient.new)
|
32
46
|
@url = PuppetLibrary::Http::Url.normalize(url)
|
33
47
|
@http_client = http_client
|
34
48
|
@query_cache = query_cache
|
@@ -27,6 +27,16 @@ module PuppetLibrary::Forge
|
|
27
27
|
# <b>Note:</b>
|
28
28
|
# The module directory must have a +Modulefile+.
|
29
29
|
class Source < PuppetLibrary::Forge::Abstract
|
30
|
+
class Config
|
31
|
+
attr_accessor :path
|
32
|
+
end
|
33
|
+
|
34
|
+
def self.configure
|
35
|
+
config = Config.new
|
36
|
+
yield(config)
|
37
|
+
Source.new(config.path)
|
38
|
+
end
|
39
|
+
|
30
40
|
CACHE_TTL_MILLIS = 500
|
31
41
|
|
32
42
|
# * <tt>:module_dir</tt> - The directory containing the module's source.
|
@@ -103,7 +103,7 @@ module PuppetLibrary
|
|
103
103
|
load_defaults!(options)
|
104
104
|
process_options!(options)
|
105
105
|
|
106
|
-
Server.
|
106
|
+
Server.configure do |server|
|
107
107
|
options[:forges].each do |(forge_type, config)|
|
108
108
|
subforge = forge_type.new(*config)
|
109
109
|
server.forge subforge
|
@@ -25,7 +25,7 @@ module PuppetLibrary
|
|
25
25
|
#
|
26
26
|
# A Rack application that can be configured as follows:
|
27
27
|
#
|
28
|
-
# server = PuppetLibrary::Server.
|
28
|
+
# server = PuppetLibrary::Server.configure do |library|
|
29
29
|
# # Look for my modules locally
|
30
30
|
# library.forge PuppetLibrary::Forge::Directory.new("/var/lib/modules")
|
31
31
|
#
|
@@ -40,12 +40,21 @@ module PuppetLibrary
|
|
40
40
|
@forge = forge
|
41
41
|
end
|
42
42
|
|
43
|
-
def forge(forge)
|
44
|
-
|
43
|
+
def forge(forge, &block)
|
44
|
+
if forge.is_a? Class
|
45
|
+
@forge.add_forge forge.configure(&block)
|
46
|
+
else
|
47
|
+
@forge.add_forge forge
|
48
|
+
end
|
45
49
|
end
|
46
50
|
end
|
47
51
|
|
48
52
|
def self.set_up(&config_block)
|
53
|
+
puts "PuppetLibrary::Server::set_up deprecated: use #configure instead"
|
54
|
+
self.configure(&config_block)
|
55
|
+
end
|
56
|
+
|
57
|
+
def self.configure
|
49
58
|
forge = Forge::Multi.new
|
50
59
|
yield(Config.new(forge))
|
51
60
|
Server.new(forge)
|
@@ -0,0 +1,103 @@
|
|
1
|
+
# Puppet Library
|
2
|
+
# Copyright (C) 2014 drrb
|
3
|
+
#
|
4
|
+
# This program is free software: you can redistribute it and/or modify
|
5
|
+
# it under the terms of the GNU General Public License as published by
|
6
|
+
# the Free Software Foundation, either version 3 of the License, or
|
7
|
+
# (at your option) any later version.
|
8
|
+
#
|
9
|
+
# This program is distributed in the hope that it will be useful,
|
10
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
11
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
12
|
+
# GNU General Public License for more details.
|
13
|
+
#
|
14
|
+
# You should have received a copy of the GNU General Public License
|
15
|
+
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
16
|
+
|
17
|
+
require 'fileutils'
|
18
|
+
require 'monitor'
|
19
|
+
require 'time'
|
20
|
+
require 'puppet_library/util/temp_dir'
|
21
|
+
|
22
|
+
module PuppetLibrary::Util
|
23
|
+
class Git
|
24
|
+
DEFAULT_CACHE_TTL_SECONDS = 60
|
25
|
+
def initialize(source, cache_path, cache_ttl_seconds = DEFAULT_CACHE_TTL_SECONDS)
|
26
|
+
@source = source
|
27
|
+
@cache_path = File.expand_path(cache_path)
|
28
|
+
@cache_ttl_seconds = cache_ttl_seconds
|
29
|
+
@git_dir = File.join(@cache_path, ".git")
|
30
|
+
@mutex = Monitor.new
|
31
|
+
end
|
32
|
+
|
33
|
+
def tags
|
34
|
+
update_cache!
|
35
|
+
git("tag").split
|
36
|
+
end
|
37
|
+
|
38
|
+
def on_tag(tag)
|
39
|
+
update_cache!
|
40
|
+
PuppetLibrary::Util::TempDir.use "git" do |path|
|
41
|
+
git "checkout #{tag}", path
|
42
|
+
yield
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def read_file(path, tag)
|
47
|
+
update_cache!
|
48
|
+
git "show refs/tags/#{tag}:#{path}"
|
49
|
+
end
|
50
|
+
|
51
|
+
def clear_cache!
|
52
|
+
@mutex.synchronize do
|
53
|
+
FileUtils.rm_rf @cache_path
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def update_cache!
|
58
|
+
create_cache unless cache_exists?
|
59
|
+
update_cache if cache_stale?
|
60
|
+
end
|
61
|
+
|
62
|
+
private
|
63
|
+
def create_cache
|
64
|
+
@mutex.synchronize do
|
65
|
+
git "clone --bare #{@source} #{@git_dir}" unless cache_exists?
|
66
|
+
FileUtils.touch fetch_file
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
def update_cache
|
71
|
+
@mutex.synchronize do
|
72
|
+
git "fetch --tags"
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
def cache_exists?
|
77
|
+
File.directory? @git_dir
|
78
|
+
end
|
79
|
+
|
80
|
+
def cache_stale?
|
81
|
+
Time.now - last_fetch > @cache_ttl_seconds
|
82
|
+
end
|
83
|
+
|
84
|
+
def last_fetch
|
85
|
+
if File.exist? fetch_file
|
86
|
+
File.stat(fetch_file).mtime
|
87
|
+
else
|
88
|
+
Time.at(0)
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
def fetch_file
|
93
|
+
File.join(@git_dir, "FETCH_HEAD")
|
94
|
+
end
|
95
|
+
|
96
|
+
def git(command, work_tree = nil)
|
97
|
+
work_tree = @cache_path unless work_tree
|
98
|
+
Open3.popen3("git --git-dir=#{@git_dir} --work-tree=#{work_tree} #{command}") do |stdin, stdout, stderr, thread|
|
99
|
+
stdout.read
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|