vendorificator 0.5.git.v0.4.0.63.g8e9d54d → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (44) hide show
  1. checksums.yaml +9 -9
  2. data/.travis.yml +2 -2
  3. data/CHANGELOG.md +10 -0
  4. data/Gemfile +5 -12
  5. data/README.md +27 -1
  6. data/Rakefile +2 -8
  7. data/features/chef_cookbook.feature +4 -4
  8. data/features/download.feature +1 -1
  9. data/features/edgecases.feature +15 -0
  10. data/features/environment.feature +3 -2
  11. data/features/fake_mode.feature +15 -0
  12. data/features/git.feature +4 -4
  13. data/features/overlay.feature +99 -0
  14. data/features/step_definitions/basic.rb +22 -0
  15. data/features/step_definitions/git.rb +16 -0
  16. data/features/step_definitions/vendorificator.rb +9 -4
  17. data/features/support/aruba_ext.rb +4 -0
  18. data/features/support/env.rb +3 -0
  19. data/features/tarball.feature +2 -2
  20. data/features/tarball_edit.feature +3 -3
  21. data/features/tool.feature +6 -4
  22. data/features/tool_shortcuts.feature +3 -3
  23. data/features/tool_specs.feature +62 -0
  24. data/features/vendor.feature +4 -3
  25. data/lib/vendorificator.rb +7 -1
  26. data/lib/vendorificator/cli.rb +12 -11
  27. data/lib/vendorificator/config.rb +32 -1
  28. data/lib/vendorificator/environment.rb +23 -27
  29. data/lib/vendorificator/hooks/chef_cookbook.rb +2 -2
  30. data/lib/vendorificator/overlay.rb +17 -0
  31. data/lib/vendorificator/segment.rb +376 -0
  32. data/lib/vendorificator/segment/overlay.rb +114 -0
  33. data/lib/vendorificator/segment/vendor.rb +115 -0
  34. data/lib/vendorificator/vendor.rb +25 -279
  35. data/lib/vendorificator/vendor/tool.rb +40 -23
  36. data/lib/vendorificator/version.rb +1 -1
  37. data/spec/vendorificator/config_spec.rb +66 -0
  38. data/spec/vendorificator/environment_spec.rb +7 -7
  39. data/spec/vendorificator/fixtures/vendorfiles/overlay.rb +4 -0
  40. data/spec/vendorificator/segment/vendor_spec.rb +19 -0
  41. data/spec/vendorificator/segment_spec.rb +106 -0
  42. data/spec/vendorificator/vendor_spec.rb +0 -89
  43. data/vendorificator.gemspec +5 -5
  44. metadata +45 -29
@@ -7,8 +7,11 @@ require 'wrong'
7
7
 
8
8
  require 'vendorificator/cli'
9
9
 
10
+ MiniGit.debug = true if ENV['CUCUMBER_DEBUG']
11
+
10
12
  ENV['GIT_AUTHOR_NAME'] = ENV['GIT_COMMITTER_NAME'] = 'Vendorificator Cucumber'
11
13
  ENV['GIT_AUTHOR_EMAIL'] = ENV['GIT_COMMITTER_EMAIL'] = 'nonexistent@example.com'
14
+ ENV['THOR_DEBUG'] = '1'
12
15
 
13
16
  World(Wrong)
14
17
 
@@ -62,5 +62,5 @@ Scenario: Tarball without a root directory
62
62
  """
63
63
  When I run vendor command "install"
64
64
  Then following has been conjured:
65
- | Name | testrepo |
66
- | With file | test/alias.c |
65
+ | Name | testrepo |
66
+ | With file | test/alias.c |
@@ -10,6 +10,6 @@ Scenario:
10
10
  """
11
11
  When I run vendor command "install"
12
12
  Then following has been conjured:
13
- | Name | testrepo |
14
- | With file | test/alias.c |
15
- | Without file | test/archive.c |
13
+ | Name | testrepo |
14
+ | With file | test/alias.c |
15
+ | Without file | test/archive.c |
@@ -23,7 +23,7 @@ Scenario: Use Gem bundler to download rubygems, and Vendorificator to vendor the
23
23
  When I run vendor command "install"
24
24
  Then following has been conjured:
25
25
  | Name | bundler |
26
- | Path | cache |
26
+ | Path | vendor/cache |
27
27
  | With file | hello-0.0.1.gem |
28
28
  | Without file | first-0.gem |
29
29
 
@@ -36,7 +36,7 @@ Scenario: Bundler correctly downloads and caches dependencies
36
36
  When I run vendor command "install"
37
37
  Then following has been conjured:
38
38
  | Name | bundler |
39
- | Path | cache |
39
+ | Path | vendor/cache |
40
40
  | Without file | hello-0.0.1.gem |
41
41
  | With file | first-0.gem |
42
42
  | With file | second-0.gem |
@@ -50,7 +50,7 @@ Scenario: directory contents are completely replaced on re-vendoring
50
50
  When I run vendor command "install"
51
51
  Then following has been conjured:
52
52
  | Name | bundler |
53
- | Path | cache |
53
+ | Path | vendor/cache |
54
54
  | With file | hello-0.0.1.gem |
55
55
  | Without file | first-0.gem |
56
56
  When I change Gemfile to:
@@ -58,10 +58,12 @@ Scenario: directory contents are completely replaced on re-vendoring
58
58
  source "file://#{ENV['FIXTURES_DIR']}/rubygems"
59
59
  gem "first"
60
60
  """
61
+ And I run `git commit -a -m bump`
61
62
  And I run vendor command "install"
62
63
  Then following has been conjured:
63
64
  | Name | bundler |
64
- | Path | cache |
65
+ | Path | vendor/cache |
65
66
  | Without file | hello-0.0.1.gem |
66
67
  | With file | first-0.gem |
67
68
  | With file | second-0.gem |
69
+
@@ -17,7 +17,7 @@ Scenario: rubygems_bundler
17
17
  When I run vendor command "install"
18
18
  Then following has been conjured:
19
19
  | Name | rubygems |
20
- | Path | cache |
20
+ | Path | vendor/cache |
21
21
  | With file | hello-0.0.1.gem |
22
22
  | Without file | first-0.gem |
23
23
 
@@ -38,14 +38,14 @@ Scenario: chef_berkshelf
38
38
  When I run vendor command "install"
39
39
  Then following has been conjured:
40
40
  | Name | cookbooks |
41
- | With file | build-essential/metadata.rb |
41
+ | With file | build-essential/metadata.rb |
42
42
 
43
43
  @berkshelf
44
44
  Scenario: postprocessing tool
45
45
  Given a repository with following Vendorfile:
46
46
  """ruby
47
47
  chef_berkshelf do
48
- FileUtils::rm_rf 'runit'
48
+ FileUtils::rm_rf 'vendor/cookbooks/runit'
49
49
  end
50
50
  """
51
51
  And a file named "Berksfile" with:
@@ -0,0 +1,62 @@
1
+ Feature: tool's specs can be specified in a flexible way
2
+
3
+ Scenario Outline:
4
+ Given a repository with following Vendorfile:
5
+ """ruby
6
+ tool 'find', :specs => <specs>,
7
+ :command => "mkdir -p vendor/find ; find . -type f -not -name found -a -not -path './.git/*' > vendor/find/found"
8
+ """
9
+ Given an empty file named "<file1>"
10
+ Given an empty file named "<file2>"
11
+ Given an empty file named "<file3>"
12
+ Given I run `git add .`
13
+ Given I run `git commit -m add`
14
+ Given an empty file named "untracked.txt"
15
+ When I run vendor command "install"
16
+ Then following has been conjured:
17
+ | Name | find |
18
+ | Path | vendor/find |
19
+ | With file | found |
20
+ And the file "vendor/find/found" should match <matches>
21
+ And the file "vendor/find/found" should not match <doesnt_match>
22
+
23
+ Examples:
24
+ | specs | file1 | file2 | file3 | matches | doesnt_match |
25
+ | '*.txt' | foo.txt | bar.txt | baz.py | /foo\.txt/ | /baz\.py/ |
26
+ | '*.txt' | foo.txt | bar.txt | baz.py | /bar\.txt/ | /baz\.py/ |
27
+ | '*.txt' | foo.txt | bar.txt | baz.py | /bar\.txt/ | /untracked\.txt/ |
28
+ | ['*.txt', '*.py' ] | foo.txt | bar.py | baz.rb | /foo\.txt/ | /baz\.rb/ |
29
+ | ['*.txt', '*.py' ] | foo.txt | bar.py | baz.rb | /bar\.py/ | /baz\.rb/ |
30
+ | '**/*.txt' | foo.txt | foo/bar.txt | foo/bar/baz.txt | /foo\.txt/ | /xxx/ |
31
+ | '**/*.txt' | foo.txt | foo/bar.txt | foo/bar/baz.txt | /bar\.txt/ | /xxx/ |
32
+ | '**/*.txt' | foo.txt | foo/bar.txt | foo/bar/baz.txt | /baz\.txt/ | /xxx/ |
33
+
34
+ Scenario: tool can be provided with extras that are not committed to segment
35
+ Given a repository with following Vendorfile:
36
+ """ruby
37
+ tool 'find',
38
+ :specs => '*.spec',
39
+ :extras => '*.txt',
40
+ :command => "mkdir -p vendor/find ; find . -type f -not -name found -a -not -path './.git/*' > vendor/find/found"
41
+ """
42
+ Given an empty file named "foo.spec"
43
+ And an empty file named "bar.txt"
44
+ And an empty file named "baz.py"
45
+ Given I run `git add .`
46
+ And I run `git commit -m add`
47
+ Given an empty file named "untracked.txt"
48
+ And an empty file named "untracked.spec"
49
+ When I run vendor command "install"
50
+ Then following has been conjured:
51
+ | Name | find |
52
+ | Path | vendor/find |
53
+ | With file | found |
54
+ And the file "vendor/find/found" should contain "foo.spec"
55
+ And the file "vendor/find/found" should contain "bar.txt"
56
+ And the file "vendor/find/found" should not contain "baz.py"
57
+ And the file "vendor/find/found" should not contain "untracked.txt"
58
+ And the file "vendor/find/found" should not contain "untracked.spec"
59
+ And the branch "vendor/find" should contain file "foo.spec"
60
+ And the branch "vendor/find" should not contain file "bar.txt"
61
+ And the branch "vendor/find" should not contain file "untracked.txt"
62
+ And the branch "vendor/find" should not contain file "untracked.spec"
@@ -11,9 +11,10 @@ Scenario:
11
11
  """
12
12
  When I run vendor command "install -v 1"
13
13
  Then the following has been conjured:
14
- | Name | generated |
15
- | Version | 0.23 |
16
- | With file | README |
14
+ | Name | generated |
15
+ | Version | 0.23 |
16
+ | With file | README |
17
17
  And the file "vendor/generated/VERSION" should contain "0.23"
18
18
  And there's a git commit note including "bar" in "foo"
19
19
  And there's a git commit note including "by Przemo" in "module_annotations"
20
+ And tag "vendor/generated/0.23" exists
@@ -1,5 +1,6 @@
1
- # Require everything except the CLI.
1
+ require 'minigit'
2
2
 
3
+ # Require everything except the CLI.
3
4
  require "vendorificator/version"
4
5
 
5
6
  require 'vendorificator/config'
@@ -7,6 +8,7 @@ require 'vendorificator/environment'
7
8
  require 'vendorificator/errors'
8
9
  require 'vendorificator/commit'
9
10
  require 'vendorificator/io_proxy'
11
+ require 'vendorificator/overlay'
10
12
 
11
13
  require 'vendorificator/vendor'
12
14
  require 'vendorificator/vendor/download'
@@ -14,3 +16,7 @@ require 'vendorificator/vendor/archive'
14
16
  require 'vendorificator/vendor/git'
15
17
  require 'vendorificator/vendor/chef_cookbook'
16
18
  require 'vendorificator/vendor/tool'
19
+
20
+ require 'vendorificator/segment'
21
+ require 'vendorificator/segment/vendor'
22
+ require 'vendorificator/segment/overlay'
@@ -15,7 +15,7 @@ require 'vendorificator'
15
15
  module Vendorificator
16
16
  class CLI < Thor
17
17
  VERBOSITY_LEVELS = {1 => :quiet, 2 => :default, 3 => :chatty, 9 => :debug}
18
- attr_reader :environment
18
+ attr_reader :environment, :verbosity
19
19
 
20
20
  check_unknown_options! :except => [:git, :diff, :log]
21
21
  stop_on_unknown_option! :git, :diff, :log
@@ -33,7 +33,7 @@ module Vendorificator
33
33
  super
34
34
  parse_options
35
35
 
36
- if self.options[:debug]
36
+ if verbosity >= 9
37
37
  MiniGit.debug = true
38
38
  end
39
39
 
@@ -44,7 +44,7 @@ module Vendorificator
44
44
 
45
45
  @environment = Vendorificator::Environment.new(
46
46
  shell,
47
- VERBOSITY_LEVELS[self.options[:verbose]] || :default,
47
+ VERBOSITY_LEVELS[verbosity] || :default,
48
48
  self.options[:file]
49
49
  )
50
50
 
@@ -60,7 +60,7 @@ module Vendorificator
60
60
  method_option :update, :type => :boolean, :default => false
61
61
  def sync
62
62
  say_status 'DEPRECATED', 'Using vendor sync is deprecated and will be removed in future versions. Use vendor install or vendor update instead.', :yellow
63
- environment.sync options.merge(:modules => modules)
63
+ environment.sync options.merge(:segments => modules)
64
64
  rescue DirtyRepoError
65
65
  fail! 'Repository is not clean.'
66
66
  rescue MissingVendorfileError
@@ -69,14 +69,14 @@ module Vendorificator
69
69
 
70
70
  desc :install, "Download and install new or updated vendor files"
71
71
  def install(*modules)
72
- environment.sync options.merge(:modules => modules)
72
+ environment.sync options.merge(:segments => modules)
73
73
  rescue DirtyRepoError
74
74
  fail! 'Repository is not clean.'
75
75
  end
76
76
 
77
77
  desc :update, "Update installed vendor files"
78
78
  def update(*modules)
79
- environment.sync options.merge(:modules => modules, :update => true)
79
+ environment.sync options.merge(:segments => modules, :update => true)
80
80
  rescue DirtyRepoError
81
81
  fail! 'Repository is not clean.'
82
82
  end
@@ -90,7 +90,7 @@ module Vendorificator
90
90
  say_status 'DEPRECATED', 'Using vendor status is deprecated and will be removed in future versions', :yellow
91
91
  say_status 'WARNING', 'Git repository is not clean', :red unless environment.clean?
92
92
 
93
- environment.each_vendor_instance(*modules) do |mod|
93
+ environment.each_segment(*modules) do |mod|
94
94
  status_line = mod.to_s
95
95
 
96
96
  updatable = mod.updatable?
@@ -163,7 +163,7 @@ module Vendorificator
163
163
  EOF
164
164
  def git(command, *args)
165
165
  modules, git_options = split_git_options(args)
166
- environment.each_vendor_instance(*modules) do |mod|
166
+ environment.each_segment(*modules) do |mod|
167
167
  unless mod.merged
168
168
  say_status 'unmerged', mod.to_s, :red
169
169
  next
@@ -232,9 +232,10 @@ EOF
232
232
  exit
233
233
  end
234
234
 
235
- if options[:verbose] && (!VERBOSITY_LEVELS.keys.include? options[:verbose])
236
- fail! "Unknown verbosity level: #{options[:verbose].inspect}"
237
- end
235
+ # figure out verbosity
236
+ @verbosity = self.options[:verbose].to_i
237
+ @verbosity = 2 if @verbosity.zero?
238
+ @verbosity = VERBOSITY_LEVELS.keys.select { |i| i < verbosity }.max unless VERBOSITY_LEVELS[@verbosity]
238
239
  end
239
240
 
240
241
  def split_git_options(args)
@@ -3,7 +3,7 @@ require 'pathname'
3
3
  module Vendorificator
4
4
  class Config
5
5
  attr_accessor :environment
6
- attr_reader :metadata
6
+ attr_reader :metadata, :overlay_instance
7
7
 
8
8
  @defaults = {}
9
9
  @modules = {}
@@ -34,6 +34,7 @@ module Vendorificator
34
34
  end
35
35
 
36
36
  def initialize(params = {})
37
+ @fake_mode = check_fake_mode
37
38
  @configuration = self.class.defaults.merge(params)
38
39
  @metadata = {}
39
40
  end
@@ -80,8 +81,38 @@ module Vendorificator
80
81
  end
81
82
  end
82
83
 
84
+ def overlay(name, options = {}, &block)
85
+ @overlay_instance = Segment::Overlay.new(
86
+ environment: environment, overlay_opts: options.merge(name: name)
87
+ )
88
+ environment.segments << @overlay_instance
89
+ yield
90
+ ensure
91
+ @overlay_instance = nil
92
+ end
93
+
94
+ # Public: Returns information whether we work in the fake mode.
95
+ #
96
+ # Returns true/false.
97
+ def fake_mode?
98
+ @fake_mode
99
+ end
100
+
83
101
  option :basedir, 'vendor'
84
102
  option :branch_prefix, 'vendor'
85
103
  option :remotes, %w(origin)
104
+
105
+ private
106
+
107
+ # Private: Check if we should work in the fake mode.
108
+ #
109
+ # Returns true/false.
110
+ def check_fake_mode
111
+ setting = MiniGit::Capturing.git(:config, 'vendorificator.stub').strip
112
+ ['', 'false', '0', 'no'].include?(setting) ? false : true
113
+ rescue MiniGit::GitError
114
+ false
115
+ end
116
+
86
117
  end
87
118
  end
@@ -1,15 +1,14 @@
1
1
  require 'pathname'
2
- require 'minigit'
3
2
  require 'awesome_print'
4
3
  require 'vendorificator/config'
5
4
 
6
5
  module Vendorificator
7
6
  class Environment
8
7
  attr_reader :config
9
- attr_accessor :vendor_instances, :io
8
+ attr_accessor :segments, :io
10
9
 
11
10
  def initialize(shell, verbosity = :default, vendorfile = nil, &block)
12
- @vendor_instances = []
11
+ @segments = []
13
12
  @io = IOProxy.new(shell, verbosity)
14
13
  @vendorfile = find_vendorfile(vendorfile)
15
14
  @vendor_block = block
@@ -87,7 +86,7 @@ module Vendorificator
87
86
  map { |sha, name| name =~ ref_rx ? [$', sha] : nil }.
88
87
  compact ]
89
88
 
90
- each_vendor_instance do |mod|
89
+ each_segment do |mod|
91
90
  ours = mod.head
92
91
  theirs = remote_branches[mod.branch_name]
93
92
  if theirs
@@ -98,7 +97,7 @@ module Vendorificator
98
97
  say_status :default, 'unchanged', mod.branch_name
99
98
  elsif fast_forwardable?(theirs, ours)
100
99
  say_status :default, 'updated', mod.name, :yellow
101
- mod.in_branch { git.merge({:ff_only => true}, theirs) } unless options[:dry_run]
100
+ mod.fast_forward theirs unless options[:dry_run]
102
101
  elsif fast_forwardable?(ours, theirs)
103
102
  say_status :default, 'older', mod.branch_name
104
103
  else
@@ -119,7 +118,7 @@ module Vendorificator
119
118
  def info(mod_name, options = {})
120
119
  load_vendorfile
121
120
 
122
- if vendor = find_vendor_instance_by_name(mod_name)
121
+ if vendor = find_module_by_name(mod_name)
123
122
  say :default, "Module name: #{vendor.name}\n"
124
123
  say :default, "Module group: #{vendor.group}\n"
125
124
  say :default, "Module merged version: #{vendor.merged_version}\n"
@@ -132,25 +131,25 @@ module Vendorificator
132
131
  end
133
132
  end
134
133
 
135
- # Public: Displays info about current modules.
134
+ # Public: Displays info about current segments.
136
135
  #
137
136
  # Returns nothing.
138
137
  def list
139
138
  load_vendorfile
140
139
 
141
- each_vendor_instance do |mod|
140
+ each_segment do |mod|
142
141
  shell.say "Module: #{mod.name}, version: #{mod.version}"
143
142
  end
144
143
  end
145
144
 
146
- # Public: Displays info about outdated modules.
145
+ # Public: Displays info about outdated segments.
147
146
  #
148
147
  # Returns nothing.
149
148
  def outdated
150
149
  load_vendorfile
151
150
 
152
151
  outdated = []
153
- each_vendor_instance do |mod|
152
+ each_segment do |mod|
154
153
  outdated << mod if [:unpulled, :unmerged, :outdated].include? mod.status
155
154
  end
156
155
 
@@ -168,7 +167,7 @@ module Vendorificator
168
167
  ensure_clean!
169
168
 
170
169
  pushable = []
171
- each_vendor_instance { |mod| pushable += mod.pushable_refs }
170
+ each_segment { |mod| pushable += mod.pushable_refs }
172
171
 
173
172
  pushable << 'refs/notes/vendor' if has_notes?
174
173
 
@@ -178,7 +177,7 @@ module Vendorificator
178
177
  end
179
178
  end
180
179
 
181
- # Public: Runs all the vendor modules.
180
+ # Public: Runs all the vendor segments.
182
181
  #
183
182
  # options - The Hash of options.
184
183
  #
@@ -190,28 +189,25 @@ module Vendorificator
190
189
  config[:use_upstream_version] = options[:update]
191
190
  metadata = metadata_snapshot
192
191
 
193
- each_vendor_instance(*options[:modules]) do |mod|
194
- say_status :default, :module, mod.name
195
- indent do
196
- mod.run!(:metadata => metadata)
197
- end
192
+ each_segment(*options[:segments]) do |mod|
193
+ mod.run!(:metadata => metadata)
198
194
  end
199
195
  end
200
196
 
201
197
  # Public: Goes through all the Vendor instances and runs the block
202
198
  #
203
- # modules - An Array of vendor modules to yield the block for.
199
+ # segments - An Array of vendor segments to yield the block for.
204
200
  #
205
201
  # Returns nothing.
206
- def each_vendor_instance(*modules)
207
- # We don't use @vendor_instances.each here, because Vendor#run! is
202
+ def each_segment(*segments)
203
+ # We don't use @segments.each here, because Vendor#run! is
208
204
  # explicitly allowed to append to instantiate new dependencies, and #each
209
205
  # fails to catch up on some Ruby implementations.
210
206
  i = 0
211
207
  while true
212
- break if i >= @vendor_instances.length
213
- mod = @vendor_instances[i]
214
- yield mod if modules.empty? || mod.included_in_list?(modules)
208
+ break if i >= @segments.length
209
+ mod = @segments[i]
210
+ yield mod if segments.empty? || mod.included_in_list?(segments)
215
211
  i += 1
216
212
  end
217
213
  end
@@ -247,7 +243,7 @@ module Vendorificator
247
243
 
248
244
  # Public: Returns module with given name
249
245
  def [](name)
250
- vendor_instances.find { |v| v.name == name }
246
+ segments.find { |v| v.name == name }
251
247
  end
252
248
 
253
249
  # Public: Loads the vendorfile.
@@ -263,7 +259,7 @@ module Vendorificator
263
259
  end
264
260
  @config.instance_eval(&@vendor_block) if @vendor_block
265
261
 
266
- each_vendor_instance{ |mod| mod.compute_dependencies! }
262
+ each_segment{ |mod| mod.compute_dependencies! }
267
263
 
268
264
  @vendorfile_loaded = true
269
265
  end
@@ -282,8 +278,8 @@ module Vendorificator
282
278
  # mod_name - The String containing the module id.
283
279
  #
284
280
  # Returns Vendor instance.
285
- def find_vendor_instance_by_name(mod_name)
286
- each_vendor_instance(mod_name) do |mod|
281
+ def find_module_by_name(mod_name)
282
+ each_segment(mod_name) do |mod|
287
283
  return mod
288
284
  end
289
285
  nil