vendorificator 0.0.1
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.
- data/.gitignore +19 -0
- data/.travis.yml +9 -0
- data/Gemfile +11 -0
- data/LICENSE +22 -0
- data/README.md +45 -0
- data/Rakefile +29 -0
- data/bin/vendor +4 -0
- data/bin/vendorify +6 -0
- data/examples/Vendorfile +25 -0
- data/features/chef_cookbook.feature +44 -0
- data/features/deprecated.feature +17 -0
- data/features/fixtures/git/testrepo/HEAD +1 -0
- data/features/fixtures/git/testrepo/config +7 -0
- data/features/fixtures/git/testrepo/description +1 -0
- data/features/fixtures/git/testrepo/hooks/applypatch-msg.sample +15 -0
- data/features/fixtures/git/testrepo/hooks/commit-msg.sample +24 -0
- data/features/fixtures/git/testrepo/hooks/post-update.sample +8 -0
- data/features/fixtures/git/testrepo/hooks/pre-applypatch.sample +14 -0
- data/features/fixtures/git/testrepo/hooks/pre-commit.sample +50 -0
- data/features/fixtures/git/testrepo/hooks/pre-rebase.sample +169 -0
- data/features/fixtures/git/testrepo/hooks/prepare-commit-msg.sample +36 -0
- data/features/fixtures/git/testrepo/hooks/update.sample +128 -0
- data/features/fixtures/git/testrepo/info/exclude +6 -0
- data/features/fixtures/git/testrepo/info/refs +5 -0
- data/features/fixtures/git/testrepo/objects/info/packs +2 -0
- data/features/fixtures/git/testrepo/objects/pack/pack-46f7621b6a6b9b1c22dd15c08d457dfedf76e55f.idx +0 -0
- data/features/fixtures/git/testrepo/objects/pack/pack-46f7621b6a6b9b1c22dd15c08d457dfedf76e55f.pack +0 -0
- data/features/fixtures/git/testrepo/packed-refs +6 -0
- data/features/fixtures/git/testrepo/refs/heads/.sentinel +0 -0
- data/features/fixtures/git/testrepo/refs/tags/.sentinel +0 -0
- data/features/fixtures/vcr_cassettes/vendorificator.yml +2375 -0
- data/features/git.feature +12 -0
- data/features/needed.feature +16 -0
- data/features/smoke.feature +14 -0
- data/features/status.feature +47 -0
- data/features/step_definitions/basic.rb +52 -0
- data/features/step_definitions/git.rb +39 -0
- data/features/step_definitions/vendorificator.rb +27 -0
- data/features/support/env.rb +32 -0
- data/features/support/transform_pattern.rb +12 -0
- data/features/support/world_git.rb +40 -0
- data/features/support/world_runs.rb +90 -0
- data/features/tarball.feature +63 -0
- data/features/tarball_edit.feature +15 -0
- data/features/vendor.feature +16 -0
- data/lib/vendorificator/cli.rb +233 -0
- data/lib/vendorificator/config.rb +72 -0
- data/lib/vendorificator/hooks/chef_cookbook.rb +23 -0
- data/lib/vendorificator/repo.rb +69 -0
- data/lib/vendorificator/vendor/archive.rb +90 -0
- data/lib/vendorificator/vendor/chef_cookbook.rb +58 -0
- data/lib/vendorificator/vendor/git.rb +47 -0
- data/lib/vendorificator/vendor.rb +260 -0
- data/lib/vendorificator/version.rb +3 -0
- data/lib/vendorificator.rb +9 -0
- data/vendorificator.gemspec +30 -0
- metadata +321 -0
@@ -0,0 +1,233 @@
|
|
1
|
+
require 'thor'
|
2
|
+
|
3
|
+
require 'vendorificator'
|
4
|
+
|
5
|
+
module Vendorificator
|
6
|
+
class CLI < Thor
|
7
|
+
include Vendorificator
|
8
|
+
|
9
|
+
check_unknown_options! :except => [:git, :diff, :log]
|
10
|
+
stop_on_unknown_option! :git, :diff, :log
|
11
|
+
|
12
|
+
default_task :sync
|
13
|
+
|
14
|
+
class_option :file, :aliases => '-f', :type => :string, :banner => 'PATH'
|
15
|
+
class_option :debug, :aliases => '-d', :type => :boolean, :default => false
|
16
|
+
class_option :quiet, :aliases => ['-q'], :default => false, :type => :boolean
|
17
|
+
class_option :modules, :type => :string, :default => '',
|
18
|
+
:banner => 'mod1,mod2,...,modN',
|
19
|
+
:desc => 'Run only for specified modules (name or path, comma separated)'
|
20
|
+
|
21
|
+
def initialize(*args)
|
22
|
+
super
|
23
|
+
Grit.debug = true if options[:debug]
|
24
|
+
Vendorificator::Config.from_file(find_vendorfile)
|
25
|
+
Vendorificator::Config[:shell] = shell
|
26
|
+
|
27
|
+
class << shell
|
28
|
+
# Make say_status always say it.
|
29
|
+
def quiet?
|
30
|
+
false
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
desc :sync, "Download new or updated vendor files"
|
36
|
+
def sync
|
37
|
+
ensure_clean_repo!
|
38
|
+
Vendorificator::Config.each_module(*modules) do |mod|
|
39
|
+
say_status :module, mod.name
|
40
|
+
begin
|
41
|
+
shell.padding += 1
|
42
|
+
mod.run!
|
43
|
+
ensure
|
44
|
+
shell.padding -= 1
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
desc "status", "List known vendor modules and their status"
|
50
|
+
def status
|
51
|
+
say_status 'WARNING', 'Git repository is not clean', :red unless repo.clean?
|
52
|
+
Vendorificator::Config.each_module(*modules) do |mod|
|
53
|
+
status_line = mod.to_s
|
54
|
+
|
55
|
+
updatable = mod.updatable?
|
56
|
+
if updatable
|
57
|
+
if updatable == true
|
58
|
+
status_line << ' (updatable)'
|
59
|
+
else
|
60
|
+
status_line << " (updatable to #{updatable.name})"
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
say_status( mod.status.to_s.gsub('_', ' '), status_line,
|
65
|
+
( mod.status==:up_to_date ? :green : :yellow ) )
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
desc :pull, "Pull upstream branches from a remote repository"
|
70
|
+
method_option :remote, :aliases => ['-r'], :default => nil
|
71
|
+
method_option :dry_run, :aliases => ['-n'], :default => false, :type => :boolean
|
72
|
+
def pull
|
73
|
+
ensure_clean_repo!
|
74
|
+
remotes = options[:remote] ? options[:remote].split(',') : conf[:remotes]
|
75
|
+
remotes.each do |remote|
|
76
|
+
indent 'remote', remote do
|
77
|
+
repo.pull(remote, options)
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
desc "git GIT_COMMAND [GIT_ARGS [...]]",
|
82
|
+
"Run a git command for specified modules"
|
83
|
+
long_desc <<EOF
|
84
|
+
Run a git command for specified modules. Within GIT_ARGS arguments,
|
85
|
+
you can use @MERGED@ and @PATH@ tags, which will be substituted with
|
86
|
+
mo#dule's most recently merged revision and full path of its work
|
87
|
+
directory.
|
88
|
+
|
89
|
+
The 'diff' and 'log' commands are simple aliases for 'git' command.
|
90
|
+
|
91
|
+
Examples:
|
92
|
+
vendor git log @MERGED@..HEAD -- @PATH@ # basic 'vendor log'
|
93
|
+
vendor git diff --stat @MERGED@ -- @PATH@ # 'vendor diff', as diffstat
|
94
|
+
EOF
|
95
|
+
method_option :only_changed, :default => false, :type => :boolean
|
96
|
+
def git(command, *args)
|
97
|
+
Vendorificator::Config.each_module(*modules) do |mod|
|
98
|
+
unless mod.merged
|
99
|
+
say_status 'unmerged', mod.to_s, :red unless options[:only_changed]
|
100
|
+
next
|
101
|
+
end
|
102
|
+
|
103
|
+
actual_args = args.dup.map do |arg|
|
104
|
+
arg.
|
105
|
+
gsub('@MERGED@', mod.merged).
|
106
|
+
gsub('@PATH@', mod.work_dir)
|
107
|
+
end
|
108
|
+
|
109
|
+
output = repo.git.native(command, {}, *actual_args)
|
110
|
+
if output.empty?
|
111
|
+
say_status 'unchanged', mod.to_s, :green unless options[:only_changed]
|
112
|
+
else
|
113
|
+
say_status 'changed', mod.to_s, :yellow
|
114
|
+
end
|
115
|
+
puts output unless options[:quiet] || output.empty?
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
desc "diff [OPTIONS] [GIT OPTIONS]",
|
120
|
+
"Show differences between work tree and upstream module(s)"
|
121
|
+
method_option :only_changed, :default => false, :type => :boolean
|
122
|
+
def diff(*args)
|
123
|
+
invoke :git, %w'diff' + args + %w'@MERGED@ -- @PATH@'
|
124
|
+
end
|
125
|
+
|
126
|
+
desc "log [OPTIONS] [GIT OPTIONS]",
|
127
|
+
"Show git log of commits added to upstream module(s)"
|
128
|
+
method_option :only_changed, :default => false, :type => :boolean
|
129
|
+
def log(*args)
|
130
|
+
invoke :git, %w'log' + args + %w'@MERGED@..HEAD -- @PATH@'
|
131
|
+
end
|
132
|
+
|
133
|
+
desc :pry, 'Pry into the binding', :hide => true
|
134
|
+
def pry
|
135
|
+
require 'pry'
|
136
|
+
binding.pry
|
137
|
+
end
|
138
|
+
|
139
|
+
def self.start
|
140
|
+
# Make --git-options always quoted
|
141
|
+
if i = ARGV.index('--git-options')
|
142
|
+
ARGV[i+1,0] = '--'
|
143
|
+
end
|
144
|
+
|
145
|
+
if ENV['FIXTURES_DIR']
|
146
|
+
require 'vcr'
|
147
|
+
VCR.configure do |c|
|
148
|
+
c.cassette_library_dir = File.join(ENV['FIXTURES_DIR'], 'vcr_cassettes')
|
149
|
+
c.default_cassette_options = { :record => :new_episodes }
|
150
|
+
c.hook_into :fakeweb
|
151
|
+
end
|
152
|
+
VCR.use_cassette(ENV['VCR_CASSETTE'] || 'vendorificator') do
|
153
|
+
super
|
154
|
+
end
|
155
|
+
else
|
156
|
+
super
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
160
|
+
private
|
161
|
+
|
162
|
+
def split_git_options(args)
|
163
|
+
case i = args.index('--git-options')
|
164
|
+
when nil then [ args, [] ]
|
165
|
+
when 0 then [ [], args[1..-1] ]
|
166
|
+
else [ args[0..(i-1)], args[(i+1)..-1] ]
|
167
|
+
end
|
168
|
+
end
|
169
|
+
|
170
|
+
def modules
|
171
|
+
options[:modules].split(',').map(&:strip)
|
172
|
+
end
|
173
|
+
|
174
|
+
def conf
|
175
|
+
Vendorificator::Config
|
176
|
+
end
|
177
|
+
|
178
|
+
def repo
|
179
|
+
Vendorificator::Config.repo
|
180
|
+
end
|
181
|
+
|
182
|
+
def fail!(message, exception_message='I give up.')
|
183
|
+
say_status('FATAL', message, :red)
|
184
|
+
raise Thor::Error, 'I give up.'
|
185
|
+
end
|
186
|
+
|
187
|
+
def indent(*args, &block)
|
188
|
+
say_status *args unless args.empty?
|
189
|
+
shell.padding += 1
|
190
|
+
yield
|
191
|
+
ensure
|
192
|
+
shell.padding -= 1
|
193
|
+
end
|
194
|
+
|
195
|
+
# Find proper Vendorfile
|
196
|
+
def find_vendorfile
|
197
|
+
given = options.file || ENV['VENDORFILE']
|
198
|
+
return Pathname.new(given).expand_path if given && !given.empty?
|
199
|
+
|
200
|
+
Pathname.pwd.ascend do |dir|
|
201
|
+
vf = dir.join('Vendorfile')
|
202
|
+
return vf if vf.exist?
|
203
|
+
|
204
|
+
vf = dir.join('config/vendor.rb')
|
205
|
+
return vf if vf.exist?
|
206
|
+
|
207
|
+
# avoid stepping above the tmp directory when testing
|
208
|
+
if ENV['VENDORIFICATOR_SPEC_RUN'] &&
|
209
|
+
dir.join('vendorificator.gemspec').exist?
|
210
|
+
raise RuntimeError, "Vendorfile not found"
|
211
|
+
end
|
212
|
+
end
|
213
|
+
|
214
|
+
raise RuntimeError, "Vendorfile not found"
|
215
|
+
end
|
216
|
+
|
217
|
+
def ensure_clean_repo!
|
218
|
+
unless repo.clean?
|
219
|
+
fail!('Repository is not clean.')
|
220
|
+
end
|
221
|
+
end
|
222
|
+
end
|
223
|
+
end
|
224
|
+
|
225
|
+
# Monkey patch over https://github.com/wycats/thor/pull/298
|
226
|
+
class Thor::Options
|
227
|
+
alias_method :_orig_current_is_switch?, :current_is_switch?
|
228
|
+
def current_is_switch?
|
229
|
+
rv = _orig_current_is_switch?
|
230
|
+
@parsing_options = false if !rv[0] && @stop_on_unknown && @parsing_options
|
231
|
+
rv
|
232
|
+
end
|
233
|
+
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
require 'pathname'
|
2
|
+
|
3
|
+
require 'mixlib/config'
|
4
|
+
|
5
|
+
require 'vendorificator/repo'
|
6
|
+
|
7
|
+
module Vendorificator
|
8
|
+
class Config
|
9
|
+
extend Mixlib::Config
|
10
|
+
|
11
|
+
configure do |c|
|
12
|
+
c[:root] = Pathname.getwd
|
13
|
+
c[:basedir] = 'vendor'
|
14
|
+
c[:branch_prefix] = 'vendor'
|
15
|
+
c[:modules] = []
|
16
|
+
c[:remotes] = %w(origin)
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.from_file(filename)
|
20
|
+
pathname = Pathname.new(filename).cleanpath.expand_path
|
21
|
+
self[:root_dir] =
|
22
|
+
if ( pathname.basename.to_s == 'vendor.rb' &&
|
23
|
+
pathname.dirname.basename.to_s == 'config' )
|
24
|
+
# Correctly recognize root dir if main config is 'config/vendor.rb'
|
25
|
+
pathname.dirname.dirname
|
26
|
+
else
|
27
|
+
pathname.dirname
|
28
|
+
end
|
29
|
+
self[:vendorfile_path] = pathname
|
30
|
+
self[:lockfile_path] = pathname.dirname.join(pathname.basename.to_s + '.lock')
|
31
|
+
super(pathname.to_s)
|
32
|
+
end
|
33
|
+
|
34
|
+
def self.repo
|
35
|
+
@repo ||= begin
|
36
|
+
git_root_path = self[:repo_dir] || _find_git_root
|
37
|
+
raise "Can't find Git repository" unless git_root_path
|
38
|
+
Vendorificator::Repo.new( git_root_path.to_s )
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def self.each_module(*modules)
|
43
|
+
module_paths = modules.map { |m| File.expand_path(m) }
|
44
|
+
|
45
|
+
# We don't use self[:modules].each here, because mod.run! is
|
46
|
+
# explicitly allowed to append to Config[:modules], and #each
|
47
|
+
# fails to catch up on some Ruby implementations.
|
48
|
+
i = 0
|
49
|
+
while true
|
50
|
+
break if i >= Vendorificator::Config[:modules].length
|
51
|
+
mod = Vendorificator::Config[:modules][i]
|
52
|
+
yield mod if
|
53
|
+
modules.empty? ||
|
54
|
+
modules.include?(mod.name) ||
|
55
|
+
module_paths.include?(mod.work_dir)
|
56
|
+
i += 1
|
57
|
+
|
58
|
+
# Add dependencies
|
59
|
+
work_dirs = Vendorificator::Config[:modules].map(&:work_dir)
|
60
|
+
Vendorificator::Config[:modules] +=
|
61
|
+
mod.dependencies.reject { |dep| work_dirs.include?(dep.work_dir) }
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
def self._find_git_root
|
66
|
+
self[:root_dir].ascend do |dir|
|
67
|
+
return dir if dir.join('.git').exist?
|
68
|
+
end
|
69
|
+
end
|
70
|
+
private_class_method :_find_git_root
|
71
|
+
end
|
72
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'chef/cookbook/metadata'
|
2
|
+
|
3
|
+
module Vendorificator::Hooks
|
4
|
+
module ChefCookbookDependencies
|
5
|
+
# Add required Chef cookbooks to vendor modules
|
6
|
+
def dependencies
|
7
|
+
ignored = Vendorificator::Config[:chef_cookbook_ignore_dependencies] || []
|
8
|
+
metadata = File.join(self.work_dir, 'metadata.rb')
|
9
|
+
|
10
|
+
unless File.exist?(metadata)
|
11
|
+
shell.say_status 'WARNING', "Metadata of #{name} does not exist at #{metadata}, could not gather dependencies", :red
|
12
|
+
return super
|
13
|
+
end
|
14
|
+
|
15
|
+
cbmd = Chef::Cookbook::Metadata.new
|
16
|
+
cbmd.from_file(metadata)
|
17
|
+
|
18
|
+
super + cbmd.dependencies.
|
19
|
+
reject { |name, version| ignored.include?(name) }.
|
20
|
+
map { |name, version| Vendorificator::Vendor::ChefCookbook.new(name) }
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
require 'grit'
|
2
|
+
|
3
|
+
module Vendorificator
|
4
|
+
class Repo < Grit::Repo
|
5
|
+
# True if repository doesn't contain uncommitted changes.
|
6
|
+
def clean?
|
7
|
+
# copy code from http://stackoverflow.com/a/3879077/16390
|
8
|
+
git.native :update_index, {}, '-q', '--ignore-submodules', '--refresh'
|
9
|
+
git.native :diff_files, {:raise => true}, '--quiet', '--ignore-submodules', '--'
|
10
|
+
git.native :diff_index, {:raise => true}, '--cached', '--quiet', 'HEAD', '--ignore-submodules', '--'
|
11
|
+
true
|
12
|
+
rescue Grit::Git::CommandFailed
|
13
|
+
false
|
14
|
+
end
|
15
|
+
|
16
|
+
# Update vendor branches & tags from an upstream repository
|
17
|
+
def pull(remote, options={})
|
18
|
+
raise RuntimeError, "Unknown remote #{remote}" unless remote_list.include?(remote)
|
19
|
+
|
20
|
+
git.fetch({}, remote)
|
21
|
+
git.fetch({:tags => true}, remote)
|
22
|
+
|
23
|
+
ref_rx = /^#{Regexp.quote(remote)}\//
|
24
|
+
remote_branches = Hash[remotes.map{|r| [$',r] if r.name =~ ref_rx }.compact]
|
25
|
+
|
26
|
+
# FIXME: should we depend on Vendorificator::Config here?
|
27
|
+
Vendorificator::Config.each_module do |mod|
|
28
|
+
remote_head = remote_branches[mod.branch_name]
|
29
|
+
ours = mod.head && mod.head.commit.sha
|
30
|
+
theirs = remote_head && remote_head.commit.sha
|
31
|
+
|
32
|
+
if remote_head
|
33
|
+
if not mod.head
|
34
|
+
say_status 'new', mod.branch_name, :yellow
|
35
|
+
git.branch({:track=>true}, mod.branch_name, remote_head.name) unless options[:dry_run]
|
36
|
+
elsif ours == theirs
|
37
|
+
say_status 'unchanged', mod.branch_name
|
38
|
+
elsif fast_forwardable?(theirs, ours)
|
39
|
+
say_status 'updated', mod.name, :yellow
|
40
|
+
unless options[:dry_run]
|
41
|
+
mod.in_branch do
|
42
|
+
git.merge({:ff_only => true}, remote_head.name)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
elsif fast_forwardable?(ours, theirs)
|
46
|
+
say_status 'older', mod.branch_name
|
47
|
+
else
|
48
|
+
say_status 'complicated', mod.branch_name, :red
|
49
|
+
indent do
|
50
|
+
say 'Merge it yourself.'
|
51
|
+
end
|
52
|
+
end
|
53
|
+
else
|
54
|
+
say_status 'unknown', mod.branch_name
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
private
|
59
|
+
|
60
|
+
def conf
|
61
|
+
Vendorificator::Config
|
62
|
+
end
|
63
|
+
|
64
|
+
def say_status(*args)
|
65
|
+
conf[:shell].say_status(*args) if conf[:shell]
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
@@ -0,0 +1,90 @@
|
|
1
|
+
require 'digest'
|
2
|
+
require 'open-uri'
|
3
|
+
require 'tempfile'
|
4
|
+
require 'uri'
|
5
|
+
|
6
|
+
require 'escape'
|
7
|
+
|
8
|
+
require 'vendorificator/vendor'
|
9
|
+
|
10
|
+
class Vendorificator::Vendor::Archive < Vendorificator::Vendor
|
11
|
+
arg_reader :url, :strip_root, :type, :checksum, :filename, :basename, :extname, :unpack
|
12
|
+
attr_reader :conjured_checksum
|
13
|
+
|
14
|
+
def initialize(name, args={}, &block)
|
15
|
+
no_url_given = !args[:url]
|
16
|
+
|
17
|
+
args[:url] ||= name
|
18
|
+
args[:filename] ||= URI::parse(args[:url]).path.split('/').last
|
19
|
+
|
20
|
+
case args[:filename]
|
21
|
+
when /\.(tar\.|t)gz$/
|
22
|
+
args[:type] ||= :targz
|
23
|
+
args[:unpack] ||= 'tar -xzf'
|
24
|
+
when /\.tar\.bz2$/
|
25
|
+
args[:type] ||= :tarbz2
|
26
|
+
args[:unpack] ||= 'tar -xjf'
|
27
|
+
when /\.zip$/
|
28
|
+
args[:type] ||= :zip
|
29
|
+
args[:unpack] ||= 'unzip'
|
30
|
+
when /\.[^\.][^\.]?[^\.]?[^\.]?$/
|
31
|
+
args[:type] ||=
|
32
|
+
begin
|
33
|
+
unless args[:unpack]
|
34
|
+
raise RuntimeError,
|
35
|
+
"Unknown file type #{$&.inspect}, please provide :unpack argument"
|
36
|
+
end
|
37
|
+
$&
|
38
|
+
end
|
39
|
+
else
|
40
|
+
args[:basename] ||= args[:filename]
|
41
|
+
args[:extname] ||= ''
|
42
|
+
unless args[:unpack] || [:targz, :tarbz2, :zip].include?(args[:type])
|
43
|
+
raise RuntimeError, "Unknown file type for #{args[:filename].inspect}, please provide :unpack or :type argument"
|
44
|
+
end
|
45
|
+
end
|
46
|
+
args[:basename] ||= $`
|
47
|
+
args[:extname] ||= $&
|
48
|
+
|
49
|
+
name = args[:basename] if no_url_given
|
50
|
+
|
51
|
+
super(name, args, &block)
|
52
|
+
end
|
53
|
+
|
54
|
+
def conjure!
|
55
|
+
shell.say_status :download, url
|
56
|
+
archive = Tempfile.new([basename, extname])
|
57
|
+
archive.write( open(url).read )
|
58
|
+
archive.close
|
59
|
+
@conjured_checksum = Digest::SHA256.file(archive.path).hexdigest
|
60
|
+
raise RuntimeError, "Checksum error" if checksum && checksum!=conjured_checksum
|
61
|
+
shell.say_status :unpack, filename
|
62
|
+
system "#{unpack} #{Escape.shell_single_word archive.path}"
|
63
|
+
if Dir.entries('.').length == 3 && !args[:no_strip_root]
|
64
|
+
root = (Dir.entries('.') - %w(.. .)).first
|
65
|
+
root_entries = Dir.entries(root) - %w(.. .)
|
66
|
+
while root_entries.include?(root)
|
67
|
+
FileUtils::mv root, root+"~"
|
68
|
+
root << "~"
|
69
|
+
end
|
70
|
+
FileUtils::mv root_entries.map { |e| File.join(root, e) }, '.'
|
71
|
+
FileUtils::rmdir root
|
72
|
+
end
|
73
|
+
super
|
74
|
+
ensure
|
75
|
+
archive.close
|
76
|
+
archive.unlink
|
77
|
+
end
|
78
|
+
|
79
|
+
def upstream_version
|
80
|
+
filename
|
81
|
+
end
|
82
|
+
|
83
|
+
def conjure_commit_message
|
84
|
+
rv = "Conjured archive #{name} from #{filename}\nOrigin: #{url}\nChecksum: #{conjured_checksum}\n"
|
85
|
+
rv << "Version: #{version}\n" if version
|
86
|
+
rv
|
87
|
+
end
|
88
|
+
|
89
|
+
install!
|
90
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
require 'net/http'
|
2
|
+
require 'uri'
|
3
|
+
require 'json'
|
4
|
+
|
5
|
+
require 'vendorificator/vendor/archive'
|
6
|
+
require 'vendorificator/hooks/chef_cookbook'
|
7
|
+
|
8
|
+
class Vendorificator::Vendor::ChefCookbook < Vendorificator::Vendor::Archive
|
9
|
+
include Vendorificator::Hooks::ChefCookbookDependencies
|
10
|
+
|
11
|
+
@method_name = :chef_cookbook
|
12
|
+
@category = :cookbooks
|
13
|
+
|
14
|
+
API_PREFIX = 'http://cookbooks.opscode.com/api/v1/cookbooks/'
|
15
|
+
|
16
|
+
def initialize(name, args={}, &block)
|
17
|
+
args[:url] ||= true # to avoid having name treated as url
|
18
|
+
args[:filename] ||= "#{name}.tgz"
|
19
|
+
|
20
|
+
super(name, args, &block)
|
21
|
+
end
|
22
|
+
|
23
|
+
def api_data(v=nil)
|
24
|
+
v = v.gsub(/[^0-9]/, '_') if v
|
25
|
+
@api_data ||= {}
|
26
|
+
@api_data[v] ||=
|
27
|
+
begin
|
28
|
+
url = "#{API_PREFIX}#{name}"
|
29
|
+
url << "/versions/#{v}" if v
|
30
|
+
JSON::load(Net::HTTP.get_response(URI.parse(url)).body)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def cookbook_data
|
35
|
+
@cookbook_data ||= api_data(version)
|
36
|
+
end
|
37
|
+
|
38
|
+
def upstream_version
|
39
|
+
URI::parse(api_data['latest_version']).path.split('/').last.gsub('_', '.')
|
40
|
+
end
|
41
|
+
|
42
|
+
def url
|
43
|
+
cookbook_data['file']
|
44
|
+
end
|
45
|
+
|
46
|
+
def conjure!
|
47
|
+
super
|
48
|
+
# Some Opscode Community tarballs include a confusing .git file,
|
49
|
+
# we don't want this.
|
50
|
+
FileUtils::rm_f '.git'
|
51
|
+
end
|
52
|
+
|
53
|
+
def conjure_commit_message
|
54
|
+
"Conjured cookbook #{name} version #{version}\nOrigin: #{url}\nChecksum: #{conjured_checksum}\n"
|
55
|
+
end
|
56
|
+
|
57
|
+
install!
|
58
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
|
3
|
+
require 'grit'
|
4
|
+
|
5
|
+
require 'vendorificator/vendor'
|
6
|
+
|
7
|
+
class Vendorificator::Vendor::Git < Vendorificator::Vendor
|
8
|
+
arg_reader :repository, :revision, :branch
|
9
|
+
attr_reader :module_repo, :conjured_revision
|
10
|
+
|
11
|
+
def initialize(name, args={}, &block)
|
12
|
+
unless args.include?(:repository)
|
13
|
+
args[:repository] = name
|
14
|
+
name = name.split('/').last.sub(/\.git$/, '')
|
15
|
+
end
|
16
|
+
super(name, args, &block)
|
17
|
+
end
|
18
|
+
|
19
|
+
def conjure!
|
20
|
+
shell.say_status :clone, repository
|
21
|
+
Grit::Git.new('.').clone({}, repository, '.')
|
22
|
+
@module_repo = Grit::Repo.new('.')
|
23
|
+
|
24
|
+
if revision
|
25
|
+
module_repo.git.checkout({:b => 'vendorified'}, revision)
|
26
|
+
elsif branch
|
27
|
+
module_repo.git.checkout({:b => 'vendorified'}, "origin/#{branch}")
|
28
|
+
end
|
29
|
+
|
30
|
+
super
|
31
|
+
@conjured_revision = module_repo.head.commit.id
|
32
|
+
FileUtils::rm_rf '.git'
|
33
|
+
end
|
34
|
+
|
35
|
+
def upstream_version
|
36
|
+
conjured_revision
|
37
|
+
end
|
38
|
+
|
39
|
+
def conjure_commit_message
|
40
|
+
rv = "Conjured git module #{name} "
|
41
|
+
rv << "version #{version} " if version
|
42
|
+
rv << "revision #{conjured_revision}"
|
43
|
+
rv
|
44
|
+
end
|
45
|
+
|
46
|
+
install!
|
47
|
+
end
|