vendorificator 0.5.git.v0.4.0.17.g26d50d8 → 0.5.git.v0.4.0.60.g9c35209

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.
@@ -6,23 +6,28 @@ require 'vendorificator/config'
6
6
  module Vendorificator
7
7
  class Environment
8
8
  attr_reader :config
9
- attr_accessor :shell, :vendor_instances
9
+ attr_accessor :vendor_instances, :io
10
10
 
11
- def initialize(vendorfile=nil, &block)
11
+ def initialize(shell, verbosity = :default, vendorfile = nil, &block)
12
12
  @vendor_instances = []
13
+ @io = IOProxy.new(shell, verbosity)
14
+ @vendorfile = find_vendorfile(vendorfile)
15
+ @vendor_block = block
13
16
 
14
17
  @config = Vendorificator::Config.new
15
18
  @config.environment = self
16
- if vendorfile || !block_given?
17
- @config.read_file(find_vendorfile(vendorfile).to_s)
18
- end
19
- @config.instance_eval(&block) if block_given?
19
+ end
20
+
21
+ def shell
22
+ io.shell
23
+ end
20
24
 
21
- self.each_vendor_instance{ |mod| mod.compute_dependencies! }
25
+ def say(*args)
26
+ io.say(*args)
22
27
  end
23
28
 
24
29
  def say_status(*args)
25
- shell.say_status(*args) if shell
30
+ io.say_status(*args)
26
31
  end
27
32
 
28
33
  # Main MiniGit instance
@@ -49,10 +54,12 @@ module Vendorificator
49
54
  #
50
55
  # Returns nothing.
51
56
  def pull_all(options = {})
57
+ load_vendorfile
58
+
52
59
  ensure_clean!
53
60
  remotes = options[:remote] ? options[:remote].split(',') : config[:remotes]
54
61
  remotes.each do |remote|
55
- indent 'remote', remote do
62
+ indent :default, 'remote', remote do
56
63
  pull(remote, options)
57
64
  end
58
65
  end
@@ -68,7 +75,10 @@ module Vendorificator
68
75
 
69
76
  git.fetch(remote)
70
77
  git.fetch({:tags => true}, remote)
71
- git.fetch(remote, 'refs/notes/vendor:refs/notes/vendor')
78
+ begin
79
+ git.fetch(remote, 'refs/notes/vendor:refs/notes/vendor')
80
+ rescue MiniGit::GitError # ignore
81
+ end
72
82
 
73
83
  ref_rx = /^refs\/remotes\/#{Regexp.quote(remote)}\//
74
84
  remote_branches = Hash[ git.capturing.show_ref.
@@ -82,20 +92,20 @@ module Vendorificator
82
92
  theirs = remote_branches[mod.branch_name]
83
93
  if theirs
84
94
  if not ours
85
- say_status 'new', mod.branch_name, :yellow
95
+ say_status :default, 'new', mod.branch_name, :yellow
86
96
  git.branch({:track => true}, mod.branch_name, theirs) unless options[:dry_run]
87
97
  elsif ours == theirs
88
- say_status 'unchanged', mod.branch_name
98
+ say_status :default, 'unchanged', mod.branch_name
89
99
  elsif fast_forwardable?(theirs, ours)
90
- say_status 'updated', mod.name, :yellow
100
+ say_status :default, 'updated', mod.name, :yellow
91
101
  mod.in_branch { git.merge({:ff_only => true}, theirs) } unless options[:dry_run]
92
102
  elsif fast_forwardable?(ours, theirs)
93
- say_status 'older', mod.branch_name
103
+ say_status :default, 'older', mod.branch_name
94
104
  else
95
- say_status 'complicated', mod.branch_name, :red
105
+ say_status :default, 'complicated', mod.branch_name, :red
96
106
  end
97
107
  else
98
- say_status 'unknown', mod.branch_name
108
+ say_status :default, 'unknown', mod.branch_name
99
109
  end
100
110
  end
101
111
  end
@@ -107,35 +117,64 @@ module Vendorificator
107
117
  #
108
118
  # Returns nothing.
109
119
  def info(mod_name, options = {})
120
+ load_vendorfile
121
+
110
122
  if vendor = find_vendor_instance_by_name(mod_name)
111
- shell.say "Module name: #{vendor.name}\n"
112
- shell.say "Module category: #{vendor.category}\n"
113
- shell.say "Module merged version: #{vendor.merged_version}\n"
114
- shell.say "Module merged notes: #{vendor.merged_notes.ai}\n"
123
+ say :default, "Module name: #{vendor.name}\n"
124
+ say :default, "Module group: #{vendor.group}\n"
125
+ say :default, "Module merged version: #{vendor.merged_version}\n"
126
+ say :default, "Module merged notes: #{vendor.merged_notes.ai}\n"
115
127
  elsif (commit = Commit.new(mod_name, git)).exists?
116
- shell.say "Branches that contain this commit: #{commit.branches.join(', ')}\n"
117
- shell.say "Vendorificator notes on this commit: #{commit.notes.ai}\n"
128
+ say :default, "Branches that contain this commit: #{commit.branches.join(', ')}\n"
129
+ say :default, "Vendorificator notes on this commit: #{commit.notes.ai}\n"
118
130
  else
119
- shell.say "Module or ref #{mod_name.inspect} not found."
131
+ say :default, "Module or ref #{mod_name.inspect} not found."
120
132
  end
121
133
  end
122
134
 
135
+ # Public: Displays info about current modules.
136
+ #
137
+ # Returns nothing.
138
+ def list
139
+ load_vendorfile
140
+
141
+ each_vendor_instance do |mod|
142
+ shell.say "Module: #{mod.name}, version: #{mod.version}"
143
+ end
144
+ end
145
+
146
+ # Public: Displays info about outdated modules.
147
+ #
148
+ # Returns nothing.
149
+ def outdated
150
+ load_vendorfile
151
+
152
+ outdated = []
153
+ each_vendor_instance do |mod|
154
+ outdated << mod if [:unpulled, :unmerged, :outdated].include? mod.status
155
+ end
156
+
157
+ outdated.each { |mod| say_status :quiet, 'outdated', mod.name }
158
+ end
159
+
123
160
  # Public: Push changes on module branches.
124
161
  #
125
162
  # options - The Hash containing options
126
163
  #
127
164
  # Returns nothing.
128
165
  def push(options = {})
166
+ load_vendorfile
167
+
129
168
  ensure_clean!
130
169
 
131
170
  pushable = []
132
- each_vendor_instance{ |mod| pushable += mod.pushable_refs }
171
+ each_vendor_instance { |mod| pushable += mod.pushable_refs }
172
+
173
+ pushable << 'refs/notes/vendor' if has_notes?
133
174
 
134
175
  remotes = options[:remote] ? options[:remote].split(',') : config[:remotes]
135
176
  remotes.each do |remote|
136
177
  git.push remote, pushable
137
- git.push remote, :tags => true
138
- git.push remote, 'refs/notes/vendor'
139
178
  end
140
179
  end
141
180
 
@@ -145,12 +184,14 @@ module Vendorificator
145
184
  #
146
185
  # Returns nothing.
147
186
  def sync(options = {})
187
+ load_vendorfile
188
+
148
189
  ensure_clean!
149
190
  config[:use_upstream_version] = options[:update]
150
191
  metadata = metadata_snapshot
151
192
 
152
193
  each_vendor_instance(*options[:modules]) do |mod|
153
- say_status :module, mod.name
194
+ say_status :default, :module, mod.name
154
195
  indent do
155
196
  mod.run!(:metadata => metadata)
156
197
  end
@@ -159,12 +200,10 @@ module Vendorificator
159
200
 
160
201
  # Public: Goes through all the Vendor instances and runs the block
161
202
  #
162
- # modules - ?
203
+ # modules - An Array of vendor modules to yield the block for.
163
204
  #
164
205
  # Returns nothing.
165
206
  def each_vendor_instance(*modules)
166
- modpaths = modules.map { |m| File.expand_path(m) }
167
-
168
207
  # We don't use @vendor_instances.each here, because Vendor#run! is
169
208
  # explicitly allowed to append to instantiate new dependencies, and #each
170
209
  # fails to catch up on some Ruby implementations.
@@ -172,9 +211,7 @@ module Vendorificator
172
211
  while true
173
212
  break if i >= @vendor_instances.length
174
213
  mod = @vendor_instances[i]
175
- yield mod if modules.empty? ||
176
- modules.include?(mod.name) ||
177
- modpaths.include?(mod.work_dir)
214
+ yield mod if modules.empty? || mod.included_in_list?(modules)
178
215
  i += 1
179
216
  end
180
217
  end
@@ -204,7 +241,8 @@ module Vendorificator
204
241
  # Public: returns `config[:root_dir]` relative to Git repository root
205
242
  def relative_root_dir
206
243
  @relative_root_dir ||= config[:root_dir].relative_path_from(
207
- Pathname.new(git.git_work_tree))
244
+ Pathname.new(git.git_work_tree)
245
+ )
208
246
  end
209
247
 
210
248
  # Public: Returns module with given name
@@ -212,16 +250,41 @@ module Vendorificator
212
250
  vendor_instances.find { |v| v.name == name }
213
251
  end
214
252
 
253
+ # Public: Loads the vendorfile.
254
+ #
255
+ # Returns nothing.
256
+ def load_vendorfile
257
+ raise RuntimeError, 'Vendorfile has been already loaded!' if @vendorfile_loaded
258
+
259
+ if @vendorfile
260
+ @config.read_file @vendorfile.to_s
261
+ else
262
+ raise MissingVendorfileError unless @vendor_block
263
+ end
264
+ @config.instance_eval(&@vendor_block) if @vendor_block
265
+
266
+ each_vendor_instance{ |mod| mod.compute_dependencies! }
267
+
268
+ @vendorfile_loaded = true
269
+ end
270
+
271
+ # Public: Checks if vendorfile has been already loaded.
272
+ #
273
+ # Returns boolean.
274
+ def vendorfile_loaded?
275
+ defined?(@vendorfile_loaded) && @vendorfile_loaded
276
+ end
277
+
215
278
  private
216
279
 
217
- # Private: Finds a vendor instance by module name.
280
+ # Private: Finds a vendor instance by module (qualified) name, path or branch.
218
281
  #
219
- # mod_name - The String containing the module name.
282
+ # mod_name - The String containing the module id.
220
283
  #
221
284
  # Returns Vendor instance.
222
285
  def find_vendor_instance_by_name(mod_name)
223
- each_vendor_instance do |mod|
224
- return mod if mod.name == mod_name
286
+ each_vendor_instance(mod_name) do |mod|
287
+ return mod
225
288
  end
226
289
  nil
227
290
  end
@@ -231,8 +294,8 @@ module Vendorificator
231
294
  # given - the optional String containing vendorfile path.
232
295
  #
233
296
  # Returns a String containing the vendorfile path.
234
- def find_vendorfile(given=nil)
235
- given = [ given, ENV['VENDORFILE'] ].find do |candidate|
297
+ def find_vendorfile(given = nil)
298
+ given = [given, ENV['VENDORFILE']].find do |candidate|
236
299
  candidate && !(candidate.respond_to?(:empty?) && candidate.empty?)
237
300
  end
238
301
  return given if given
@@ -247,11 +310,11 @@ module Vendorificator
247
310
  # avoid stepping above the tmp directory when testing
248
311
  if ENV['VENDORIFICATOR_SPEC_RUN'] &&
249
312
  dir.join('vendorificator.gemspec').exist?
250
- raise ArgumentError, "Vendorfile not found"
313
+ break
251
314
  end
252
315
  end
253
316
 
254
- raise ArgumentError, "Vendorfile not found"
317
+ return nil
255
318
  end
256
319
 
257
320
  # Private: Aborts on a dirty repository.
@@ -264,12 +327,23 @@ module Vendorificator
264
327
  # Private: Indents the output.
265
328
  #
266
329
  # Returns nothing.
267
- def indent(*args, &block)
268
- say_status *args unless args.empty?
330
+ def indent(verb_level = :default, *args, &block)
331
+ say_status verb_level, *args unless args.empty?
269
332
  shell.padding += 1 if shell
270
333
  yield
271
334
  ensure
272
335
  shell.padding -= 1 if shell
273
336
  end
337
+
338
+ # Private: Checks if there are git vendor notes.
339
+ #
340
+ # Returns true/false.
341
+ def has_notes?
342
+ git.capturing.rev_parse({:quiet => true, :verify => true}, 'refs/notes/vendor')
343
+ true
344
+ rescue MiniGit::GitError
345
+ false
346
+ end
347
+
274
348
  end
275
349
  end
@@ -1,3 +1,4 @@
1
1
  module Vendorificator
2
2
  class DirtyRepoError < StandardError; end
3
+ class MissingVendorfileError < StandardError; end
3
4
  end
@@ -26,7 +26,7 @@ module Vendorificator::Hooks
26
26
  metadata = File.join(self.work_dir, 'metadata.rb')
27
27
 
28
28
  unless File.exist?(metadata)
29
- shell.say_status 'WARNING', "Metadata of #{name} does not exist at #{metadata}, could not gather dependencies", :red
29
+ say_status :quiet, 'WARNING', "Metadata of #{name} does not exist at #{metadata}, could not gather dependencies", :red
30
30
  return super
31
31
  end
32
32
 
@@ -0,0 +1,46 @@
1
+ require 'stringio'
2
+
3
+ module Vendorificator
4
+ class IOProxy < StringIO
5
+ attr_reader :shell
6
+
7
+ def initialize(shell, verbosity = :default)
8
+ @shell = shell
9
+ @verbosity = verbosity
10
+
11
+ super()
12
+ capture_stdout
13
+ end
14
+
15
+ def puts(value, verb_level = :default)
16
+ @orig_stdout.puts value if should_speak?(verb_level)
17
+ super
18
+ end
19
+
20
+ def say_status(verb_level, *args)
21
+ write args[0..1].join(' ' * @shell.padding)
22
+ @shell.say_status(*args) if @shell && should_speak?(verb_level)
23
+ end
24
+
25
+ def say(verb_level, *args)
26
+ write args[0]
27
+ @shell.say(*args) if @shell && should_speak?(verb_level)
28
+ end
29
+
30
+ private
31
+
32
+ def capture_stdout
33
+ @orig_stdout = $stdout
34
+
35
+ $stdout = self
36
+ end
37
+
38
+ def should_speak?(level)
39
+ levels = {:quiet => 1, :default => 2, :chatty => 3, :debug => 9}
40
+ raise "Unknown verbosity level: #{level.inspect}" if levels[level].nil?
41
+
42
+ levels[level] <= levels[@verbosity]
43
+ end
44
+ end
45
+ end
46
+
@@ -13,9 +13,9 @@ module Vendorificator
13
13
  attr_reader :conjured_checksum, :conjured_filesize
14
14
 
15
15
  def conjure!
16
- shell.say_status :download, url
16
+ say_status :default, :download, url
17
17
  archive = download_file
18
- shell.say_status :unpack, filename
18
+ say_status :default, :unpack, filename
19
19
  unpack_file archive
20
20
  add_archive_metadata
21
21
  super
@@ -10,7 +10,7 @@ module Vendorificator
10
10
  include Hooks::ChefCookbookDependencies
11
11
 
12
12
  @method_name = :chef_cookbook
13
- @category = :cookbooks
13
+ @group = :cookbooks
14
14
 
15
15
  API_PREFIX = 'http://cookbooks.opscode.com/api/v1/cookbooks/'
16
16
 
@@ -11,11 +11,11 @@ module Vendorificator
11
11
  attr_reader :conjured_checksum, :conjured_filesize
12
12
 
13
13
  def path
14
- args[:path] || category
14
+ args[:path] || group
15
15
  end
16
16
 
17
17
  def conjure!
18
- shell.say_status :download, url
18
+ say_status :default, :download, url
19
19
  File.open name, 'w' do |outf|
20
20
  outf.write( open(url).read )
21
21
  end
@@ -7,7 +7,7 @@ module Vendorificator
7
7
  attr_reader :conjured_revision
8
8
 
9
9
  def conjure!
10
- shell.say_status :clone, repository
10
+ say_status :default, :clone, repository
11
11
  MiniGit.git :clone, repository, '.'
12
12
  local_git = MiniGit.new('.')
13
13
 
@@ -8,7 +8,7 @@ module Vendorificator
8
8
  class Vendor
9
9
 
10
10
  class << self
11
- attr_accessor :category, :method_name
11
+ attr_accessor :group, :method_name
12
12
 
13
13
  def arg_reader(*names)
14
14
  names.each do |name|
@@ -41,19 +41,28 @@ module Vendorificator
41
41
  end
42
42
 
43
43
  def path
44
- args[:path] || _join(category, name)
44
+ args[:path] || _join(group, name)
45
45
  end
46
46
 
47
47
  def shell
48
- @shell ||= config[:shell] || Thor::Shell::Basic.new
48
+ @environment.shell
49
49
  end
50
50
 
51
- def category
52
- defined?(@category) ? @category : self.class.category
51
+ def say(verb_level= :default, &block)
52
+ output = yield
53
+ @environment.say verb_level, output
54
+ end
55
+
56
+ def say_status(*args, &block)
57
+ @environment.say_status(*args, &block)
58
+ end
59
+
60
+ def group
61
+ defined?(@group) ? @group : self.class.group
53
62
  end
54
63
 
55
64
  def branch_name
56
- _join(config[:branch_prefix], category, name)
65
+ _join(config[:branch_prefix], group, name)
57
66
  end
58
67
 
59
68
  def to_s
@@ -167,14 +176,17 @@ module Vendorificator
167
176
  rescue MiniGit::GitError
168
177
  nil
169
178
  end
170
- Dir.mktmpdir("vendor-#{category}-#{name}") do |tmpdir|
179
+ Dir.mktmpdir("vendor-#{group}-#{name}") do |tmpdir|
171
180
  clone_opts = {:shared => true, :no_checkout => true}
172
181
  clone_opts[:branch] = branch_name if branch_exists
173
- MiniGit.git(:clone, clone_opts, git.git_dir, tmpdir)
174
- tmpgit = MiniGit::new(tmpdir)
182
+ say { MiniGit::Capturing.git(:clone, clone_opts, git.git_dir, tmpdir) }
183
+ tmpgit = MiniGit.new(tmpdir)
184
+ #TODO: Silence/handle the stderr output from git-checkout
185
+ tmpgit.capturing.checkout({orphan: true}, branch_name) unless branch_exists
175
186
  tmpgit.fetch(git.git_dir, "refs/notes/vendor:refs/notes/vendor") if notes_exist
176
- tmpgit.checkout({orphan: true}, branch_name) unless branch_exists
177
- tmpgit.rm( { :r => true, :f => true, :q => true, :ignore_unmatch => true }, '.') if options[:clean] || !branch_exists
187
+ if options[:clean] || !branch_exists
188
+ tmpgit.rm({ :r => true, :f => true, :q => true, :ignore_unmatch => true }, '.')
189
+ end
178
190
 
179
191
  begin
180
192
  @git = tmpgit
@@ -185,6 +197,7 @@ module Vendorificator
185
197
  @git = nil
186
198
  end
187
199
 
200
+ #TODO: Silence/handle the stderr output from git-fetch
188
201
  git.fetch(tmpdir)
189
202
  git.fetch({tags: true}, tmpdir)
190
203
  git.fetch(tmpdir,
@@ -197,16 +210,16 @@ module Vendorificator
197
210
  case status
198
211
 
199
212
  when :up_to_date
200
- shell.say_status 'up to date', self.to_s
213
+ say_status :default, 'up to date', self.to_s
201
214
 
202
215
  when :unpulled, :unmerged
203
- shell.say_status 'merging', self.to_s, :yellow
216
+ say_status :default, 'merging', self.to_s, :yellow
204
217
  git.merge({:no_edit => true, :no_ff => true}, tagged_sha1)
205
218
  postprocess! if self.respond_to? :postprocess!
206
219
  compute_dependencies!
207
220
 
208
221
  when :outdated, :new
209
- shell.say_status 'fetching', self.to_s, :yellow
222
+ say_status :default, 'fetching', self.to_s, :yellow
210
223
  begin
211
224
  shell.padding += 1
212
225
  before_conjure!
@@ -237,7 +250,7 @@ module Vendorificator
237
250
  end
238
251
 
239
252
  else
240
- say_status self.status, "I'm unsure what to do.", :red
253
+ say_status :quiet, self.status, "I'm unsure what to do.", :red
241
254
  end
242
255
  end
243
256
 
@@ -245,30 +258,41 @@ module Vendorificator
245
258
  block.call(self) if block
246
259
  end
247
260
 
248
- #
249
261
  # Hook points
250
262
  def git_add_extra_paths ; [] ; end
251
263
  def before_conjure! ; end
252
264
  def compute_dependencies! ; end
253
265
 
254
266
  def pushable_refs
255
- created_tags.
256
- map { |tag| '+' << tag }.
257
- unshift("+refs/heads/#{branch_name}")
267
+ created_tags.unshift("refs/heads/#{branch_name}")
258
268
  end
259
269
 
260
270
  def metadata
261
271
  default = {
262
272
  :module_version => version,
263
- :module_category => @category,
273
+ :module_group => @group,
264
274
  }
265
275
  default.merge @metadata
266
276
  end
267
277
 
278
+ def included_in_list?(module_list)
279
+ modpaths = module_list.map { |m| File.expand_path(m) }
280
+
281
+ module_list.include?(name) ||
282
+ module_list.include?("#{group}/#{name}") ||
283
+ modpaths.include?(File.expand_path(work_dir)) ||
284
+ module_list.include?(merged) ||
285
+ module_list.include?(branch_name)
286
+ end
287
+
268
288
  private
269
289
 
270
290
  def parse_initialize_args(args = {})
271
- @category = args.delete(:category) if args.key?(:category)
291
+ @group = args.delete(:group) if args.key?(:group)
292
+ if args.key?(:category)
293
+ @group ||= args.delete(:category)
294
+ say_status :default, 'DEPRECATED', 'Using :category option is deprecated and will be removed in future versions. Use :group instead.'
295
+ end
272
296
 
273
297
  unless (hooks = Array(args.delete(:hooks))).empty?
274
298
  hooks.each do |hook|
@@ -282,7 +306,7 @@ module Vendorificator
282
306
  end
283
307
 
284
308
  def tag_name_base
285
- _join('vendor', category, name)
309
+ _join('vendor', group, name)
286
310
  end
287
311
 
288
312
  def conjure_commit_message
@@ -294,7 +318,9 @@ module Vendorificator
294
318
  end
295
319
 
296
320
  def tagged_sha1
297
- @tagged_sha1 ||= git.capturing.rev_parse({:verify => true, :quiet => true}, "refs/tags/#{tag_name}^{commit}").strip
321
+ @tagged_sha1 ||= git.capturing.rev_parse(
322
+ {:verify => true, :quiet => true}, "refs/tags/#{tag_name}^{commit}"
323
+ ).strip
298
324
  rescue MiniGit::GitError
299
325
  nil
300
326
  end
@@ -340,7 +366,7 @@ module Vendorificator
340
366
  git.capturing.commit :m => conjure_commit_message
341
367
  git.capturing.notes({:ref => 'vendor'}, 'add', {:m => conjure_note(environment_metadata)}, 'HEAD')
342
368
  git.capturing.tag( { :a => true, :m => tag_message }, tag_name )
343
- shell.say_status :tag, tag_name
369
+ say_status :default, :tag, tag_name
344
370
  end
345
371
 
346
372
  # Private: Merges all the data we use for the commit note.
@@ -6,6 +6,7 @@ require 'vendorificator/config'
6
6
  require 'vendorificator/environment'
7
7
  require 'vendorificator/errors'
8
8
  require 'vendorificator/commit'
9
+ require 'vendorificator/io_proxy'
9
10
 
10
11
  require 'vendorificator/vendor'
11
12
  require 'vendorificator/vendor/download'
data/spec/spec_helper.rb CHANGED
@@ -44,8 +44,9 @@ class MiniTest::Spec
44
44
  include Vendorificator::Spec::Helpers::Wrong
45
45
 
46
46
  before do
47
- _git = stub
48
- _git.stubs(:capturing).returns(stub)
47
+ _git = stub('git')
48
+ _capturing = stub('git.capturing')
49
+ _git.stubs(:capturing).returns(_capturing)
49
50
  Vendorificator::Environment.any_instance.stubs(:git).returns(_git)
50
51
  end
51
52
 
@@ -55,7 +56,7 @@ class MiniTest::Spec
55
56
 
56
57
  def basic_environment
57
58
  @basic_environment ||= Vendorificator::Environment.new(
58
- 'spec/vendorificator/fixtures/vendorfiles/empty_vendor.rb'
59
+ Thor::Shell::Basic.new, :quiet, nil
59
60
  )
60
61
  end
61
62