librarian 0.0.25 → 0.0.26

Sign up to get free protection for your applications and to get access to all the features.
Files changed (40) hide show
  1. data/.gitignore +4 -0
  2. data/CHANGELOG.md +21 -0
  3. data/README.md +6 -1
  4. data/lib/librarian/action/persist_resolution_mixin.rb +51 -0
  5. data/lib/librarian/action/resolve.rb +3 -38
  6. data/lib/librarian/action/update.rb +4 -38
  7. data/lib/librarian/chef/dsl.rb +1 -0
  8. data/lib/librarian/chef/source.rb +1 -0
  9. data/lib/librarian/chef/source/github.rb +27 -0
  10. data/lib/librarian/chef/source/site.rb +51 -51
  11. data/lib/librarian/cli.rb +31 -23
  12. data/lib/librarian/cli/manifest_presenter.rb +36 -22
  13. data/lib/librarian/dependency.rb +60 -0
  14. data/lib/librarian/environment.rb +13 -1
  15. data/lib/librarian/linter/source_linter.rb +55 -0
  16. data/lib/librarian/lockfile/parser.rb +39 -16
  17. data/lib/librarian/manifest.rb +8 -0
  18. data/lib/librarian/manifest_set.rb +5 -7
  19. data/lib/librarian/mock/source/mock.rb +4 -21
  20. data/lib/librarian/resolution.rb +1 -1
  21. data/lib/librarian/resolver.rb +15 -12
  22. data/lib/librarian/resolver/implementation.rb +166 -75
  23. data/lib/librarian/source/basic_api.rb +45 -0
  24. data/lib/librarian/source/git.rb +4 -22
  25. data/lib/librarian/source/git/repository.rb +1 -1
  26. data/lib/librarian/source/local.rb +0 -7
  27. data/lib/librarian/source/path.rb +4 -22
  28. data/lib/librarian/version.rb +1 -1
  29. data/librarian.gemspec +3 -3
  30. data/spec/functional/chef/source/site_spec.rb +150 -100
  31. data/spec/functional/source/git/repository_spec.rb +2 -1
  32. data/spec/{functional → integration}/chef/source/git_spec.rb +12 -3
  33. data/spec/integration/chef/source/site_spec.rb +217 -0
  34. data/spec/support/cli_macro.rb +4 -12
  35. data/spec/support/method_patch_macro.rb +30 -0
  36. data/spec/unit/config/database_spec.rb +8 -0
  37. data/spec/unit/dependency_spec.rb +176 -0
  38. data/spec/unit/environment_spec.rb +76 -7
  39. data/spec/unit/resolver_spec.rb +2 -2
  40. metadata +52 -46
@@ -105,7 +105,7 @@ module Librarian
105
105
  def remote_branch_names
106
106
  remotes = remote_names.sort_by(&:length).reverse
107
107
 
108
- command = %W(branch -r)
108
+ command = %W(branch -r --no-color)
109
109
  names = run!(command, :chdir => true).strip.lines.map(&:strip).to_a
110
110
  names.each{|n| n.gsub!(/\s*->.*$/, "")}
111
111
  names.reject!{|n| n =~ /\/HEAD$/}
@@ -16,13 +16,6 @@ module Librarian
16
16
  [manifest].compact
17
17
  end
18
18
 
19
- def manifest(name, version, dependencies)
20
- manifest = Manifest.new(self, name)
21
- manifest.version = version
22
- manifest.dependencies = dependencies
23
- manifest
24
- end
25
-
26
19
  def manifest_search_paths(name)
27
20
  @manifest_search_paths ||= { }
28
21
  @manifest_search_paths[name] ||= begin
@@ -1,32 +1,14 @@
1
+ require 'librarian/source/basic_api'
1
2
  require 'librarian/source/local'
2
3
 
3
4
  module Librarian
4
5
  module Source
5
6
  class Path
6
-
7
+ include BasicApi
7
8
  include Local
8
9
 
9
- class << self
10
-
11
- LOCK_NAME = 'PATH'
12
-
13
- def lock_name
14
- LOCK_NAME
15
- end
16
-
17
- def from_lock_options(environment, options)
18
- new(environment, options[:remote], options.reject{|k, v| k == :remote})
19
- end
20
-
21
- def from_spec_args(environment, path, options)
22
- recognized_options = []
23
- unrecognized_options = options.keys - recognized_options
24
- unrecognized_options.empty? or raise Error, "unrecognized options: #{unrecognized_options.join(", ")}"
25
-
26
- new(environment, path, options)
27
- end
28
-
29
- end
10
+ lock_name 'PATH'
11
+ spec_options []
30
12
 
31
13
  attr_accessor :environment
32
14
  private :environment=
@@ -1,3 +1,3 @@
1
1
  module Librarian
2
- VERSION = "0.0.25"
2
+ VERSION = "0.0.26"
3
3
  end
@@ -2,15 +2,15 @@
2
2
 
3
3
  Gem::Specification.new do |s|
4
4
  s.name = "librarian"
5
- s.version = "0.0.25"
5
+ s.version = "0.0.26"
6
6
 
7
7
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
8
8
  s.authors = ["Jay Feldblum"]
9
- s.date = "2012-10-12"
9
+ s.date = "2012-12-30"
10
10
  s.description = "Librarian"
11
11
  s.email = ["y_feldblum@yahoo.com"]
12
12
  s.executables = ["librarian-chef", "librarian-mock"]
13
- s.files = [".gitignore", ".rspec", ".travis.yml", "CHANGELOG.md", "Gemfile", "MIT-LICENSE", "README.md", "Rakefile", "bin/librarian-chef", "bin/librarian-mock", "lib/librarian.rb", "lib/librarian/action.rb", "lib/librarian/action/base.rb", "lib/librarian/action/clean.rb", "lib/librarian/action/ensure.rb", "lib/librarian/action/install.rb", "lib/librarian/action/resolve.rb", "lib/librarian/action/update.rb", "lib/librarian/chef.rb", "lib/librarian/chef/cli.rb", "lib/librarian/chef/dsl.rb", "lib/librarian/chef/environment.rb", "lib/librarian/chef/extension.rb", "lib/librarian/chef/integration/knife.rb", "lib/librarian/chef/manifest_reader.rb", "lib/librarian/chef/source.rb", "lib/librarian/chef/source/git.rb", "lib/librarian/chef/source/local.rb", "lib/librarian/chef/source/path.rb", "lib/librarian/chef/source/site.rb", "lib/librarian/chef/templates/Cheffile", "lib/librarian/cli.rb", "lib/librarian/cli/manifest_presenter.rb", "lib/librarian/config.rb", "lib/librarian/config/database.rb", "lib/librarian/config/file_source.rb", "lib/librarian/config/hash_source.rb", "lib/librarian/config/source.rb", "lib/librarian/dependency.rb", "lib/librarian/dsl.rb", "lib/librarian/dsl/receiver.rb", "lib/librarian/dsl/target.rb", "lib/librarian/environment.rb", "lib/librarian/error.rb", "lib/librarian/helpers.rb", "lib/librarian/lockfile.rb", "lib/librarian/lockfile/compiler.rb", "lib/librarian/lockfile/parser.rb", "lib/librarian/logger.rb", "lib/librarian/manifest.rb", "lib/librarian/manifest_set.rb", "lib/librarian/mock.rb", "lib/librarian/mock/cli.rb", "lib/librarian/mock/dsl.rb", "lib/librarian/mock/environment.rb", "lib/librarian/mock/extension.rb", "lib/librarian/mock/source.rb", "lib/librarian/mock/source/mock.rb", "lib/librarian/mock/source/mock/registry.rb", "lib/librarian/resolution.rb", "lib/librarian/resolver.rb", "lib/librarian/resolver/implementation.rb", "lib/librarian/source.rb", "lib/librarian/source/git.rb", "lib/librarian/source/git/repository.rb", "lib/librarian/source/local.rb", "lib/librarian/source/path.rb", "lib/librarian/spec.rb", "lib/librarian/spec_change_set.rb", "lib/librarian/specfile.rb", "lib/librarian/support/abstract_method.rb", "lib/librarian/ui.rb", "lib/librarian/version.rb", "librarian.gemspec", "spec/functional/chef/cli_spec.rb", "spec/functional/chef/source/git_spec.rb", "spec/functional/chef/source/site_spec.rb", "spec/functional/source/git/repository_spec.rb", "spec/support/cli_macro.rb", "spec/support/with_env_macro.rb", "spec/unit/action/base_spec.rb", "spec/unit/action/clean_spec.rb", "spec/unit/action/ensure_spec.rb", "spec/unit/action/install_spec.rb", "spec/unit/config/database_spec.rb", "spec/unit/dependency_spec.rb", "spec/unit/dsl_spec.rb", "spec/unit/environment_spec.rb", "spec/unit/lockfile/parser_spec.rb", "spec/unit/lockfile_spec.rb", "spec/unit/manifest_set_spec.rb", "spec/unit/manifest_spec.rb", "spec/unit/mock/source/mock_spec.rb", "spec/unit/resolver_spec.rb", "spec/unit/source/git_spec.rb", "spec/unit/spec_change_set_spec.rb"]
13
+ s.files = [".gitignore", ".rspec", ".travis.yml", "CHANGELOG.md", "Gemfile", "MIT-LICENSE", "README.md", "Rakefile", "bin/librarian-chef", "bin/librarian-mock", "lib/librarian.rb", "lib/librarian/action.rb", "lib/librarian/action/base.rb", "lib/librarian/action/clean.rb", "lib/librarian/action/ensure.rb", "lib/librarian/action/install.rb", "lib/librarian/action/persist_resolution_mixin.rb", "lib/librarian/action/resolve.rb", "lib/librarian/action/update.rb", "lib/librarian/chef.rb", "lib/librarian/chef/cli.rb", "lib/librarian/chef/dsl.rb", "lib/librarian/chef/environment.rb", "lib/librarian/chef/extension.rb", "lib/librarian/chef/integration/knife.rb", "lib/librarian/chef/manifest_reader.rb", "lib/librarian/chef/source.rb", "lib/librarian/chef/source/git.rb", "lib/librarian/chef/source/github.rb", "lib/librarian/chef/source/local.rb", "lib/librarian/chef/source/path.rb", "lib/librarian/chef/source/site.rb", "lib/librarian/chef/templates/Cheffile", "lib/librarian/cli.rb", "lib/librarian/cli/manifest_presenter.rb", "lib/librarian/config.rb", "lib/librarian/config/database.rb", "lib/librarian/config/file_source.rb", "lib/librarian/config/hash_source.rb", "lib/librarian/config/source.rb", "lib/librarian/dependency.rb", "lib/librarian/dsl.rb", "lib/librarian/dsl/receiver.rb", "lib/librarian/dsl/target.rb", "lib/librarian/environment.rb", "lib/librarian/error.rb", "lib/librarian/helpers.rb", "lib/librarian/linter/source_linter.rb", "lib/librarian/lockfile.rb", "lib/librarian/lockfile/compiler.rb", "lib/librarian/lockfile/parser.rb", "lib/librarian/logger.rb", "lib/librarian/manifest.rb", "lib/librarian/manifest_set.rb", "lib/librarian/mock.rb", "lib/librarian/mock/cli.rb", "lib/librarian/mock/dsl.rb", "lib/librarian/mock/environment.rb", "lib/librarian/mock/extension.rb", "lib/librarian/mock/source.rb", "lib/librarian/mock/source/mock.rb", "lib/librarian/mock/source/mock/registry.rb", "lib/librarian/resolution.rb", "lib/librarian/resolver.rb", "lib/librarian/resolver/implementation.rb", "lib/librarian/source.rb", "lib/librarian/source/basic_api.rb", "lib/librarian/source/git.rb", "lib/librarian/source/git/repository.rb", "lib/librarian/source/local.rb", "lib/librarian/source/path.rb", "lib/librarian/spec.rb", "lib/librarian/spec_change_set.rb", "lib/librarian/specfile.rb", "lib/librarian/support/abstract_method.rb", "lib/librarian/ui.rb", "lib/librarian/version.rb", "librarian.gemspec", "spec/functional/chef/cli_spec.rb", "spec/functional/chef/source/site_spec.rb", "spec/functional/source/git/repository_spec.rb", "spec/integration/chef/source/git_spec.rb", "spec/integration/chef/source/site_spec.rb", "spec/support/cli_macro.rb", "spec/support/method_patch_macro.rb", "spec/support/with_env_macro.rb", "spec/unit/action/base_spec.rb", "spec/unit/action/clean_spec.rb", "spec/unit/action/ensure_spec.rb", "spec/unit/action/install_spec.rb", "spec/unit/config/database_spec.rb", "spec/unit/dependency_spec.rb", "spec/unit/dsl_spec.rb", "spec/unit/environment_spec.rb", "spec/unit/lockfile/parser_spec.rb", "spec/unit/lockfile_spec.rb", "spec/unit/manifest_set_spec.rb", "spec/unit/manifest_spec.rb", "spec/unit/mock/source/mock_spec.rb", "spec/unit/resolver_spec.rb", "spec/unit/source/git_spec.rb", "spec/unit/spec_change_set_spec.rb"]
14
14
  s.homepage = ""
15
15
  s.require_paths = ["lib"]
16
16
  s.rubyforge_project = "librarian"
@@ -4,9 +4,8 @@ require 'webmock'
4
4
 
5
5
  require 'librarian'
6
6
  require 'librarian/helpers'
7
- require 'librarian/action/resolve'
8
- require 'librarian/action/install'
9
7
  require 'librarian/chef'
8
+ require 'librarian/linter/source_linter'
10
9
 
11
10
  module Librarian
12
11
  module Chef
@@ -20,7 +19,8 @@ module Librarian
20
19
  project_path = project_path.dirname until project_path.join("Rakefile").exist?
21
20
  project_path
22
21
  end
23
- let(:tmp_path) { project_path.join("tmp/spec/chef/site-source") }
22
+ let(:tmp_path) { project_path.join("tmp/spec/functional/chef/source/site") }
23
+ after { tmp_path.rmtree if tmp_path && tmp_path.exist? }
24
24
  let(:sample_path) { tmp_path.join("sample") }
25
25
  let(:sample_metadata) do
26
26
  Helpers.strip_heredoc(<<-METADATA)
@@ -73,141 +73,191 @@ module Librarian
73
73
  WebMock.reset!
74
74
  end
75
75
 
76
- context "a single dependency with a site source" do
76
+ let(:repo_path) { tmp_path.join("methods") }
77
+ before { repo_path.mkpath }
77
78
 
78
- context "resolving" do
79
- let(:repo_path) { tmp_path.join("repo/resolve") }
80
- before do
81
- repo_path.rmtree if repo_path.exist?
82
- repo_path.mkpath
83
- repo_path.join("cookbooks").mkpath
84
- cheffile = Helpers.strip_heredoc(<<-CHEFFILE)
85
- #!/usr/bin/env ruby
86
- cookbook "sample", :site => #{api_url.inspect}
87
- CHEFFILE
88
- repo_path.join("Cheffile").open("wb") { |f| f.write(cheffile) }
89
- end
90
-
91
- context "the resolve" do
92
- it "should not raise an exception" do
93
- expect { Action::Resolve.new(env).run }.to_not raise_error
94
- end
79
+ describe "lint" do
80
+ it "lints" do
81
+ Librarian::Linter::SourceLinter.lint! described_class
82
+ end
83
+ end
84
+
85
+ describe "class methods" do
86
+
87
+ describe ".lock_name" do
88
+ specify { described_class.lock_name.should == "SITE" }
89
+ end
90
+
91
+ describe ".from_spec_args" do
92
+ it "gives the expected source" do
93
+ args = { }
94
+ source = described_class.from_spec_args(env, api_url, args)
95
+ source.uri.should == api_url
95
96
  end
96
97
 
97
- context "the results" do
98
- before { Action::Resolve.new(env).run }
98
+ it "raises on unexpected args" do
99
+ args = {:k => 3}
100
+ expect { described_class.from_spec_args(env, api_url, args) }.
101
+ to raise_error Librarian::Error, "unrecognized options: k"
102
+ end
103
+ end
99
104
 
100
- it "should create the lockfile" do
101
- repo_path.join("Cheffile.lock").should exist
102
- end
105
+ describe ".from_lock_options" do
106
+ it "gives the expected source" do
107
+ options = {:remote => api_url}
108
+ source = described_class.from_lock_options(env, options)
109
+ source.uri.should == api_url
110
+ end
103
111
 
104
- it "should not attempt to install the cookbok" do
105
- repo_path.join("cookbooks/sample").should_not exist
106
- end
112
+ it "roundtrips" do
113
+ options = {:remote => api_url}
114
+ source = described_class.from_lock_options(env, options)
115
+ source.to_lock_options.should == options
107
116
  end
108
117
  end
109
118
 
110
- context "intalling" do
111
- let(:repo_path) { tmp_path.join("repo/install") }
112
- before do
113
- repo_path.rmtree if repo_path.exist?
114
- repo_path.mkpath
115
- repo_path.join("cookbooks").mkpath
116
- cheffile = Helpers.strip_heredoc(<<-CHEFFILE)
117
- #!/usr/bin/env ruby
118
- cookbook "sample", :site => #{api_url.inspect}
119
- CHEFFILE
120
- repo_path.join("Cheffile").open("wb") { |f| f.write(cheffile) }
119
+ end
121
120
 
122
- Action::Resolve.new(env).run
121
+ describe "instance methods" do
122
+ let(:source) { described_class.new(env, api_url) }
123
+
124
+ describe "#manifests" do
125
+ it "gives a list of all manifests" do
126
+ manifests = source.manifests("sample")
127
+ manifests.should have(1).item
128
+ manifest = manifests.first
129
+ manifest.source.should be source
130
+ manifest.version.should == Manifest::Version.new("0.6.5")
131
+ manifest.dependencies.should be_empty
123
132
  end
133
+ end
124
134
 
125
- context "the install" do
126
- it "should not raise an exception" do
127
- expect { Action::Install.new(env).run }.to_not raise_error
128
- end
135
+ describe "#fetch_version" do
136
+ it "fetches the version based on extra" do
137
+ extra = "#{api_url}/cookbooks/sample/versions/0_6_5"
138
+ source.fetch_version("sample", extra).should == "0.6.5"
129
139
  end
140
+ end
130
141
 
131
- context "the results" do
132
- before { Action::Install.new(env).run }
142
+ describe "#fetch_dependencies" do
143
+ it "fetches the dependencies based on extra" do
144
+ extra = "#{api_url}/cookbooks/sample/versions/0_6_5"
145
+ source.fetch_dependencies("sample", "0.6.5", extra).should == [ ]
146
+ end
147
+ end
133
148
 
134
- it "should create the lockfile" do
135
- repo_path.join("Cheffile.lock").should exist
136
- end
149
+ describe "#pinned?" do
150
+ it "returns false" do
151
+ source.should_not be_pinned
152
+ end
153
+ end
137
154
 
138
- it "should create a directory for the cookbook" do
139
- repo_path.join("cookbooks/sample").should exist
140
- end
155
+ describe "#unpin!" do
156
+ it "is a no-op" do
157
+ source.unpin!
158
+ end
159
+ end
160
+
161
+ describe "#install!" do
162
+ before { env.install_path.mkpath }
141
163
 
142
- it "should copy the cookbook files into the cookbook directory" do
143
- repo_path.join("cookbooks/sample/metadata.rb").should exist
164
+ context "directly" do
165
+ it "installs the manifest" do
166
+ manifest = Manifest.new(source, "sample")
167
+ manifest.version = "0.6.5"
168
+ source.install!(manifest)
169
+ text = env.install_path.join("sample/metadata.rb").read
170
+ text.should == sample_metadata
144
171
  end
145
172
  end
146
- end
147
173
 
148
- context "resolving and separately installing" do
149
- let(:repo_path) { tmp_path.join("repo/resolve-install") }
150
- before do
151
- repo_path.rmtree if repo_path.exist?
152
- repo_path.mkpath
153
- repo_path.join("cookbooks").mkpath
154
- cheffile = Helpers.strip_heredoc(<<-CHEFFILE)
155
- #!/usr/bin/env ruby
156
- cookbook "sample", :site => #{api_url.inspect}
157
- CHEFFILE
158
- repo_path.join("Cheffile").open("wb") { |f| f.write(cheffile) }
159
-
160
- Action::Resolve.new(env).run
161
- repo_path.join("tmp").rmtree if repo_path.join("tmp").exist?
162
- end
163
-
164
- context "the install" do
165
- it "should not raise an exception" do
166
- expect { Action::Install.new(env).run }.to_not raise_error
174
+ context "indirectly" do
175
+ it "installs the manifest" do
176
+ manifest = source.manifests("sample").first
177
+ source.install!(manifest)
178
+ text = env.install_path.join("sample/metadata.rb").read
179
+ text.should == sample_metadata
167
180
  end
168
181
  end
182
+ end
169
183
 
170
- context "the results" do
171
- before { Action::Install.new(env).run }
184
+ describe "#to_spec_args" do
185
+ it "gives the expected spec args" do
186
+ source.to_spec_args.should == [api_url, { }]
187
+ end
188
+ end
172
189
 
173
- it "should create a directory for the cookbook" do
174
- repo_path.join("cookbooks/sample").should exist
175
- end
190
+ describe "#to_lock_options" do
191
+ it "gives the expected lock options" do
192
+ source.to_lock_options.should == {:remote => api_url}
193
+ end
176
194
 
177
- it "should copy the cookbook files into the cookbook directory" do
178
- repo_path.join("cookbooks/sample/metadata.rb").should exist
179
- end
195
+ it "roundtrips" do
196
+ options = source.to_lock_options
197
+ described_class.from_lock_options(env, options).should == source
180
198
  end
181
199
  end
182
200
 
183
201
  end
184
202
 
185
- context "when the repo path has a space" do
203
+ describe "following http redirects" do
204
+ let(:source) { described_class.new(env, api_url) }
186
205
 
187
- let(:repo_path) { tmp_path.join("repo/with extra spaces/resolve") }
206
+ def redirect_to(url)
207
+ {:status => 302, :headers => {"Location" => url}}
208
+ end
188
209
 
189
- before do
190
- repo_path.rmtree if repo_path.exist?
191
- repo_path.mkpath
192
- repo_path.join("cookbooks").mkpath
210
+ context "with a sequence of http redirects" do
211
+ before do
212
+ stub_request(:get, "#{api_url}/cookbooks/sample").
213
+ to_return redirect_to "#{api_url}/cookbooks/sample-1"
214
+ stub_request(:get, "#{api_url}/cookbooks/sample-1").
215
+ to_return redirect_to "#{api_url}/cookbooks/sample-2"
216
+ stub_request(:get, "#{api_url}/cookbooks/sample-2").
217
+ to_return(:body => JSON.dump(sample_index_data))
218
+ end
193
219
 
194
- cheffile = Helpers.strip_heredoc(<<-CHEFFILE)
195
- #!/usr/bin/env ruby
196
- cookbook "sample", :site => #{api_url.inspect}
197
- CHEFFILE
198
- repo_path.join("Cheffile").open("wb") { |f| f.write(cheffile) }
220
+ it "follows a sequence of redirects" do
221
+ manifest = source.manifests("sample").first
222
+ manifest.version.to_s.should == "0.6.5"
223
+ end
199
224
  end
200
225
 
201
- after do
202
- repo_path.rmtree
203
- end
226
+ context "with too many http redirects" do
227
+ before do
228
+ stub_request(:get, "#{api_url}/cookbooks/sample").
229
+ to_return redirect_to "#{api_url}/cookbooks/sample-1"
230
+ (1 .. 11).each do |i|
231
+ stub_request(:get, "#{api_url}/cookbooks/sample-#{i}").
232
+ to_return redirect_to "#{api_url}/cookbooks/sample-#{i + 1}"
233
+ end
234
+ stub_request(:get, "#{api_url}/cookbooks/sample-12").
235
+ to_return(:body => JSON.dump(sample_index_data))
236
+ end
204
237
 
205
- context "the resolution" do
206
- it "should not raise an exception" do
207
- expect { Action::Resolve.new(env).run }.to_not raise_error
238
+ it "raises, warning of too many redirects" do
239
+ expect { source.manifests("sample").first }.
240
+ to raise_error Librarian::Error, /because too many redirects!/
208
241
  end
209
242
  end
210
243
 
244
+ context "with a redirect cycle" do
245
+ before do
246
+ stub_request(:get, "#{api_url}/cookbooks/sample").
247
+ to_return redirect_to "#{api_url}/cookbooks/sample-1"
248
+ (1 .. 8).each do |i|
249
+ stub_request(:get, "#{api_url}/cookbooks/sample-#{i}").
250
+ to_return redirect_to "#{api_url}/cookbooks/sample-#{i + 1}"
251
+ end
252
+ stub_request(:get, "#{api_url}/cookbooks/sample-9").
253
+ to_return redirect_to "#{api_url}/cookbooks/sample-6"
254
+ end
255
+
256
+ it "raises, warning of a redirect cycle" do
257
+ expect { source.manifests("sample").first }.
258
+ to raise_error Librarian::Error, /because redirect cycle!/
259
+ end
260
+ end
211
261
  end
212
262
 
213
263
  end
@@ -15,7 +15,8 @@ describe Librarian::Source::Git::Repository do
15
15
  project_path = project_path.dirname until project_path.join("Rakefile").exist?
16
16
  project_path
17
17
  end
18
- let(:tmp_path) { project_path + "tmp/spec/unit/source/git/repository-spec" }
18
+ let(:tmp_path) { project_path + "tmp/spec/functional/source/git/repository" }
19
+ after { tmp_path.rmtree if tmp_path && tmp_path.exist? }
19
20
  let(:git_source_path) { tmp_path + SecureRandom.hex(16) }
20
21
  let(:branch) { "the-branch" }
21
22
  let(:tag) { "the-tag" }
@@ -19,7 +19,8 @@ module Librarian
19
19
  project_path = project_path.dirname until project_path.join("Rakefile").exist?
20
20
  project_path
21
21
  end
22
- let(:tmp_path) { project_path.join("tmp/spec/chef/git-source") }
22
+ let(:tmp_path) { project_path.join("tmp/spec/integration/chef/source/git") }
23
+ after { tmp_path.rmtree if tmp_path && tmp_path.exist? }
23
24
 
24
25
  let(:cookbooks_path) { tmp_path.join("cookbooks") }
25
26
 
@@ -49,7 +50,7 @@ module Librarian
49
50
  METADATA
50
51
  end
51
52
 
52
- before :all do
53
+ before do
53
54
  sample_path.rmtree if sample_path.exist?
54
55
  sample_path.mkpath
55
56
  sample_path.join("metadata.rb").open("wb") { |f| f.write(sample_metadata) }
@@ -217,7 +218,7 @@ module Librarian
217
218
  METADATA
218
219
  end
219
220
 
220
- before :all do
221
+ before do
221
222
  git_path.rmtree if git_path.exist?
222
223
  git_path.mkpath
223
224
  sample_path.mkpath
@@ -304,6 +305,14 @@ module Librarian
304
305
  let(:git_path) { tmp_path.join("big-git-repo") }
305
306
  let(:repo_path) { tmp_path.join("repo/resolve") }
306
307
  before do
308
+ git_path.rmtree if git_path.exist?
309
+ git_path.mkpath
310
+ Dir.chdir(git_path) do
311
+ `git init`
312
+ `touch not-a-metadata`
313
+ `git add .`
314
+ `git commit -m "Initial commit."`
315
+ end
307
316
  repo_path.rmtree if repo_path.exist?
308
317
  repo_path.mkpath
309
318
  repo_path.join("cookbooks").mkpath
@@ -0,0 +1,217 @@
1
+ require 'pathname'
2
+ require 'json'
3
+ require 'webmock'
4
+
5
+ require 'librarian'
6
+ require 'librarian/helpers'
7
+ require 'librarian/action/resolve'
8
+ require 'librarian/action/install'
9
+ require 'librarian/chef'
10
+
11
+ module Librarian
12
+ module Chef
13
+ module Source
14
+ describe Site do
15
+
16
+ include WebMock::API
17
+
18
+ let(:project_path) do
19
+ project_path = Pathname.new(__FILE__).expand_path
20
+ project_path = project_path.dirname until project_path.join("Rakefile").exist?
21
+ project_path
22
+ end
23
+ let(:tmp_path) { project_path.join("tmp/spec/integration/chef/source/site") }
24
+ after { tmp_path.rmtree if tmp_path && tmp_path.exist? }
25
+ let(:sample_path) { tmp_path.join("sample") }
26
+ let(:sample_metadata) do
27
+ Helpers.strip_heredoc(<<-METADATA)
28
+ version "0.6.5"
29
+ METADATA
30
+ end
31
+
32
+ let(:api_url) { "http://site.cookbooks.com" }
33
+
34
+ let(:sample_index_data) do
35
+ {
36
+ "name" => "sample",
37
+ "versions" => [
38
+ "#{api_url}/cookbooks/sample/versions/0_6_5"
39
+ ]
40
+ }
41
+ end
42
+ let(:sample_0_6_5_data) do
43
+ {
44
+ "version" => "0.6.5",
45
+ "file" => "#{api_url}/cookbooks/sample/versions/0_6_5/file.tar.gz"
46
+ }
47
+ end
48
+ let(:sample_0_6_5_package) do
49
+ s = StringIO.new
50
+ z = Zlib::GzipWriter.new(s, Zlib::NO_COMPRESSION)
51
+ t = Archive::Tar::Minitar::Output.new(z)
52
+ t.tar.add_file_simple("sample/metadata.rb", :mode => 0700,
53
+ :size => sample_metadata.bytesize){|io| io.write(sample_metadata)}
54
+ t.close
55
+ z.close unless z.closed?
56
+ s.string
57
+ end
58
+
59
+ # depends on repo_path being defined in each context
60
+ let(:env) { Environment.new(:project_path => repo_path) }
61
+
62
+ before do
63
+ stub_request(:get, "#{api_url}/cookbooks/sample").
64
+ to_return(:body => JSON.dump(sample_index_data))
65
+
66
+ stub_request(:get, "#{api_url}/cookbooks/sample/versions/0_6_5").
67
+ to_return(:body => JSON.dump(sample_0_6_5_data))
68
+
69
+ stub_request(:get, "#{api_url}/cookbooks/sample/versions/0_6_5/file.tar.gz").
70
+ to_return(:body => sample_0_6_5_package)
71
+ end
72
+
73
+ after do
74
+ WebMock.reset!
75
+ end
76
+
77
+ context "a single dependency with a site source" do
78
+
79
+ context "resolving" do
80
+ let(:repo_path) { tmp_path.join("repo/resolve") }
81
+ before do
82
+ repo_path.rmtree if repo_path.exist?
83
+ repo_path.mkpath
84
+ repo_path.join("cookbooks").mkpath
85
+ cheffile = Helpers.strip_heredoc(<<-CHEFFILE)
86
+ #!/usr/bin/env ruby
87
+ cookbook "sample", :site => #{api_url.inspect}
88
+ CHEFFILE
89
+ repo_path.join("Cheffile").open("wb") { |f| f.write(cheffile) }
90
+ end
91
+
92
+ context "the resolve" do
93
+ it "should not raise an exception" do
94
+ expect { Action::Resolve.new(env).run }.to_not raise_error
95
+ end
96
+ end
97
+
98
+ context "the results" do
99
+ before { Action::Resolve.new(env).run }
100
+
101
+ it "should create the lockfile" do
102
+ repo_path.join("Cheffile.lock").should exist
103
+ end
104
+
105
+ it "should not attempt to install the cookbok" do
106
+ repo_path.join("cookbooks/sample").should_not exist
107
+ end
108
+ end
109
+ end
110
+
111
+ context "intalling" do
112
+ let(:repo_path) { tmp_path.join("repo/install") }
113
+ before do
114
+ repo_path.rmtree if repo_path.exist?
115
+ repo_path.mkpath
116
+ repo_path.join("cookbooks").mkpath
117
+ cheffile = Helpers.strip_heredoc(<<-CHEFFILE)
118
+ #!/usr/bin/env ruby
119
+ cookbook "sample", :site => #{api_url.inspect}
120
+ CHEFFILE
121
+ repo_path.join("Cheffile").open("wb") { |f| f.write(cheffile) }
122
+
123
+ Action::Resolve.new(env).run
124
+ end
125
+
126
+ context "the install" do
127
+ it "should not raise an exception" do
128
+ expect { Action::Install.new(env).run }.to_not raise_error
129
+ end
130
+ end
131
+
132
+ context "the results" do
133
+ before { Action::Install.new(env).run }
134
+
135
+ it "should create the lockfile" do
136
+ repo_path.join("Cheffile.lock").should exist
137
+ end
138
+
139
+ it "should create a directory for the cookbook" do
140
+ repo_path.join("cookbooks/sample").should exist
141
+ end
142
+
143
+ it "should copy the cookbook files into the cookbook directory" do
144
+ repo_path.join("cookbooks/sample/metadata.rb").should exist
145
+ end
146
+ end
147
+ end
148
+
149
+ context "resolving and separately installing" do
150
+ let(:repo_path) { tmp_path.join("repo/resolve-install") }
151
+ before do
152
+ repo_path.rmtree if repo_path.exist?
153
+ repo_path.mkpath
154
+ repo_path.join("cookbooks").mkpath
155
+ cheffile = Helpers.strip_heredoc(<<-CHEFFILE)
156
+ #!/usr/bin/env ruby
157
+ cookbook "sample", :site => #{api_url.inspect}
158
+ CHEFFILE
159
+ repo_path.join("Cheffile").open("wb") { |f| f.write(cheffile) }
160
+
161
+ Action::Resolve.new(env).run
162
+ repo_path.join("tmp").rmtree if repo_path.join("tmp").exist?
163
+ end
164
+
165
+ context "the install" do
166
+ it "should not raise an exception" do
167
+ expect { Action::Install.new(env).run }.to_not raise_error
168
+ end
169
+ end
170
+
171
+ context "the results" do
172
+ before { Action::Install.new(env).run }
173
+
174
+ it "should create a directory for the cookbook" do
175
+ repo_path.join("cookbooks/sample").should exist
176
+ end
177
+
178
+ it "should copy the cookbook files into the cookbook directory" do
179
+ repo_path.join("cookbooks/sample/metadata.rb").should exist
180
+ end
181
+ end
182
+ end
183
+
184
+ end
185
+
186
+ context "when the repo path has a space" do
187
+
188
+ let(:repo_path) { tmp_path.join("repo/with extra spaces/resolve") }
189
+
190
+ before do
191
+ repo_path.rmtree if repo_path.exist?
192
+ repo_path.mkpath
193
+ repo_path.join("cookbooks").mkpath
194
+
195
+ cheffile = Helpers.strip_heredoc(<<-CHEFFILE)
196
+ #!/usr/bin/env ruby
197
+ cookbook "sample", :site => #{api_url.inspect}
198
+ CHEFFILE
199
+ repo_path.join("Cheffile").open("wb") { |f| f.write(cheffile) }
200
+ end
201
+
202
+ after do
203
+ repo_path.rmtree
204
+ end
205
+
206
+ context "the resolution" do
207
+ it "should not raise an exception" do
208
+ expect { Action::Resolve.new(env).run }.to_not raise_error
209
+ end
210
+ end
211
+
212
+ end
213
+
214
+ end
215
+ end
216
+ end
217
+ end