puppet-library 0.9.1 → 0.10.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 +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
|