librarian 0.0.9 → 0.0.10

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.
Files changed (64) hide show
  1. data/CHANGELOG.md +4 -0
  2. data/lib/librarian.rb +5 -178
  3. data/lib/librarian/action.rb +5 -0
  4. data/lib/librarian/action/base.rb +22 -0
  5. data/lib/librarian/action/clean.rb +56 -0
  6. data/lib/librarian/action/ensure.rb +24 -0
  7. data/lib/librarian/action/install.rb +101 -0
  8. data/lib/librarian/action/resolve.rb +81 -0
  9. data/lib/librarian/action/update.rb +76 -0
  10. data/lib/librarian/chef/cli.rb +7 -2
  11. data/lib/librarian/chef/dsl.rb +0 -3
  12. data/lib/librarian/chef/environment.rb +19 -0
  13. data/lib/librarian/chef/extension.rb +1 -16
  14. data/lib/librarian/chef/integration/knife.rb +9 -16
  15. data/lib/librarian/chef/source/git.rb +0 -2
  16. data/lib/librarian/chef/source/local.rb +1 -74
  17. data/lib/librarian/chef/source/local/manifest.rb +82 -0
  18. data/lib/librarian/chef/source/path.rb +0 -2
  19. data/lib/librarian/chef/source/site.rb +9 -89
  20. data/lib/librarian/chef/source/site/manifest.rb +94 -0
  21. data/lib/librarian/cli.rb +56 -17
  22. data/lib/librarian/dependency.rb +2 -2
  23. data/lib/librarian/dsl.rb +15 -5
  24. data/lib/librarian/dsl/receiver.rb +2 -0
  25. data/lib/librarian/dsl/target.rb +13 -1
  26. data/lib/librarian/environment.rb +94 -0
  27. data/lib/librarian/error.rb +4 -0
  28. data/lib/librarian/helpers/debug.rb +6 -6
  29. data/lib/librarian/lockfile.rb +7 -5
  30. data/lib/librarian/lockfile/compiler.rb +5 -4
  31. data/lib/librarian/lockfile/parser.rb +6 -5
  32. data/lib/librarian/manifest.rb +2 -2
  33. data/lib/librarian/mock/cli.rb +6 -1
  34. data/lib/librarian/mock/dsl.rb +0 -3
  35. data/lib/librarian/mock/environment.rb +24 -0
  36. data/lib/librarian/mock/extension.rb +1 -20
  37. data/lib/librarian/mock/source/mock.rb +7 -7
  38. data/lib/librarian/mock/source/mock/registry.rb +16 -12
  39. data/lib/librarian/resolver.rb +5 -116
  40. data/lib/librarian/resolver/implementation.rb +117 -0
  41. data/lib/librarian/source/git.rb +8 -7
  42. data/lib/librarian/source/git/repository.rb +7 -5
  43. data/lib/librarian/source/local.rb +1 -1
  44. data/lib/librarian/source/path.rb +7 -6
  45. data/lib/librarian/spec_change_set.rb +6 -5
  46. data/lib/librarian/specfile.rb +10 -4
  47. data/lib/librarian/version.rb +1 -1
  48. data/librarian.gemspec +1 -0
  49. data/spec/functional/chef/source/git_spec.rb +177 -89
  50. data/spec/functional/chef/source/site_spec.rb +111 -52
  51. data/spec/unit/action/base_spec.rb +18 -0
  52. data/spec/unit/action/clean_spec.rb +133 -0
  53. data/spec/unit/action/ensure_spec.rb +37 -0
  54. data/spec/unit/action/install_spec.rb +113 -0
  55. data/spec/unit/dsl_spec.rb +15 -13
  56. data/spec/unit/environment_spec.rb +9 -0
  57. data/spec/unit/lockfile_spec.rb +15 -4
  58. data/spec/unit/mock/source/mock.rb +22 -0
  59. data/spec/unit/resolver_spec.rb +24 -24
  60. data/spec/unit/spec_change_set_spec.rb +29 -25
  61. metadata +47 -19
  62. data/lib/librarian/chef/particularity.rb +0 -9
  63. data/lib/librarian/mock/particularity.rb +0 -9
  64. data/lib/librarian/particularity.rb +0 -7
@@ -1,7 +1,11 @@
1
+ require 'pathname'
2
+ require 'json'
1
3
  require 'webmock'
2
4
 
3
5
  require 'librarian'
4
6
  require 'librarian/helpers'
7
+ require 'librarian/action/resolve'
8
+ require 'librarian/action/install'
5
9
  require 'librarian/chef'
6
10
 
7
11
  module Librarian
@@ -41,10 +45,13 @@ module Librarian
41
45
  }
42
46
  end
43
47
 
48
+ # depends on repo_path being defined in each context
49
+ let(:env) { Environment.new(:project_path => repo_path) }
50
+
44
51
  before :all do
45
52
  sample_path.rmtree if sample_path.exist?
46
53
  sample_path.mkpath
47
- sample_path.join('metadata.rb').open('wb') { |f| f.write(sample_metadata) }
54
+ sample_path.join("metadata.rb").open("wb") { |f| f.write(sample_metadata) }
48
55
  Dir.chdir(sample_path.dirname) do
49
56
  system "tar --create --gzip --file sample.tar.gz #{sample_path.basename}"
50
57
  end
@@ -67,58 +74,109 @@ module Librarian
67
74
 
68
75
  context "a single dependency with a site source" do
69
76
 
70
- it "should resolve" do
71
- repo_path = tmp_path.join("repo/resolve")
72
- repo_path.rmtree if repo_path.exist?
73
- repo_path.mkpath
74
- repo_path.join("cookbooks").mkpath
75
- cheffile = Helpers.strip_heredoc(<<-CHEFFILE)
76
- #!/usr/bin/env ruby
77
- cookbook "sample", :site => #{api_url.inspect}
78
- CHEFFILE
79
- repo_path.join("Cheffile").open("wb") { |f| f.write(cheffile) }
80
- Chef.stub!(:project_path) { repo_path }
81
-
82
- Chef.resolve!
83
- repo_path.join("Cheffile.lock").should exist
84
- repo_path.join("cookbooks/sample").should_not exist
77
+ context "resolving" do
78
+ let(:repo_path) { tmp_path.join("repo/resolve") }
79
+ before do
80
+ repo_path.rmtree if repo_path.exist?
81
+ repo_path.mkpath
82
+ repo_path.join("cookbooks").mkpath
83
+ cheffile = Helpers.strip_heredoc(<<-CHEFFILE)
84
+ #!/usr/bin/env ruby
85
+ cookbook "sample", :site => #{api_url.inspect}
86
+ CHEFFILE
87
+ repo_path.join("Cheffile").open("wb") { |f| f.write(cheffile) }
88
+ end
89
+
90
+ context "the resolve" do
91
+ it "should not raise an exception" do
92
+ expect { Action::Resolve.new(env).run }.to_not raise_error
93
+ end
94
+ end
95
+
96
+ context "the results" do
97
+ before { Action::Resolve.new(env).run }
98
+
99
+ it "should create the lockfile" do
100
+ repo_path.join("Cheffile.lock").should exist
101
+ end
102
+
103
+ it "should not attempt to install the cookbok" do
104
+ repo_path.join("cookbooks/sample").should_not exist
105
+ end
106
+ end
85
107
  end
86
108
 
87
- it "should install" do
88
- repo_path = tmp_path.join("repo/install")
89
- repo_path.rmtree if repo_path.exist?
90
- repo_path.mkpath
91
- repo_path.join("cookbooks").mkpath
92
- cheffile = Helpers.strip_heredoc(<<-CHEFFILE)
93
- #!/usr/bin/env ruby
94
- cookbook "sample", :site => #{api_url.inspect}
95
- CHEFFILE
96
- repo_path.join("Cheffile").open("wb") { |f| f.write(cheffile) }
97
- Chef.stub!(:project_path) { repo_path }
98
-
99
- Chef.install!
100
- repo_path.join("Cheffile.lock").should exist
101
- repo_path.join("cookbooks/sample").should exist
102
- repo_path.join("cookbooks/sample/metadata.rb").should exist
109
+ context "intalling" do
110
+ let(:repo_path) { tmp_path.join("repo/install") }
111
+ before do
112
+ repo_path.rmtree if repo_path.exist?
113
+ repo_path.mkpath
114
+ repo_path.join("cookbooks").mkpath
115
+ cheffile = Helpers.strip_heredoc(<<-CHEFFILE)
116
+ #!/usr/bin/env ruby
117
+ cookbook "sample", :site => #{api_url.inspect}
118
+ CHEFFILE
119
+ repo_path.join("Cheffile").open("wb") { |f| f.write(cheffile) }
120
+
121
+ Action::Resolve.new(env).run
122
+ end
123
+
124
+ context "the install" do
125
+ it "should not raise an exception" do
126
+ expect { Action::Install.new(env).run }.to_not raise_error
127
+ end
128
+ end
129
+
130
+ context "the results" do
131
+ before { Action::Install.new(env).run }
132
+
133
+ it "should create the lockfile" do
134
+ repo_path.join("Cheffile.lock").should exist
135
+ end
136
+
137
+ it "should create a directory for the cookbook" do
138
+ repo_path.join("cookbooks/sample").should exist
139
+ end
140
+
141
+ it "should copy the cookbook files into the cookbook directory" do
142
+ repo_path.join("cookbooks/sample/metadata.rb").should exist
143
+ end
144
+ end
103
145
  end
104
146
 
105
- it "should resolve and separately install" do
106
- repo_path = tmp_path.join("repo/resolve-install")
107
- repo_path.rmtree if repo_path.exist?
108
- repo_path.mkpath
109
- repo_path.join("cookbooks").mkpath
110
- cheffile = Helpers.strip_heredoc(<<-CHEFFILE)
111
- #!/usr/bin/env ruby
112
- cookbook "sample", :site => #{api_url.inspect}
113
- CHEFFILE
114
- repo_path.join("Cheffile").open("wb") { |f| f.write(cheffile) }
115
- Chef.stub!(:project_path) { repo_path }
116
-
117
- Chef.resolve!
118
- repo_path.join("tmp").rmtree if repo_path.join("tmp").exist?
119
- Chef.install!
120
- repo_path.join("cookbooks/sample").should exist
121
- repo_path.join("cookbooks/sample/metadata.rb").should exist
147
+ context "resolving and separately installing" do
148
+ let(:repo_path) { tmp_path.join("repo/resolve-install") }
149
+ before do
150
+ repo_path.rmtree if repo_path.exist?
151
+ repo_path.mkpath
152
+ repo_path.join("cookbooks").mkpath
153
+ cheffile = Helpers.strip_heredoc(<<-CHEFFILE)
154
+ #!/usr/bin/env ruby
155
+ cookbook "sample", :site => #{api_url.inspect}
156
+ CHEFFILE
157
+ repo_path.join("Cheffile").open("wb") { |f| f.write(cheffile) }
158
+
159
+ Action::Resolve.new(env).run
160
+ repo_path.join("tmp").rmtree if repo_path.join("tmp").exist?
161
+ end
162
+
163
+ context "the install" do
164
+ it "should not raise an exception" do
165
+ expect { Action::Install.new(env).run }.to_not raise_error
166
+ end
167
+ end
168
+
169
+ context "the results" do
170
+ before { Action::Install.new(env).run }
171
+
172
+ it "should create a directory for the cookbook" do
173
+ repo_path.join("cookbooks/sample").should exist
174
+ end
175
+
176
+ it "should copy the cookbook files into the cookbook directory" do
177
+ repo_path.join("cookbooks/sample/metadata.rb").should exist
178
+ end
179
+ end
122
180
  end
123
181
 
124
182
  end
@@ -137,15 +195,16 @@ module Librarian
137
195
  cookbook "sample", :site => #{api_url.inspect}
138
196
  CHEFFILE
139
197
  repo_path.join("Cheffile").open("wb") { |f| f.write(cheffile) }
140
- Chef.stub!(:project_path) { repo_path }
141
198
  end
142
199
 
143
200
  after do
144
201
  repo_path.rmtree
145
202
  end
146
203
 
147
- it "should resolve" do
148
- expect { Chef.resolve! }.to_not raise_error
204
+ context "the resolution" do
205
+ it "should not raise an exception" do
206
+ expect { Action::Resolve.new(env).run }.to_not raise_error
207
+ end
149
208
  end
150
209
 
151
210
  end
@@ -0,0 +1,18 @@
1
+ require "librarian/action/base"
2
+
3
+ module Librarian
4
+ describe Action::Base do
5
+
6
+ let(:env) { mock }
7
+ let(:action) { described_class.new(env) }
8
+
9
+ subject { action }
10
+
11
+ it { should respond_to :environment }
12
+
13
+ it "should have the environment that was assigned to it" do
14
+ action.environment.should be env
15
+ end
16
+
17
+ end
18
+ end
@@ -0,0 +1,133 @@
1
+ require "librarian/action/clean"
2
+
3
+ module Librarian
4
+ describe Action::Clean do
5
+
6
+ let(:env) { mock }
7
+ let(:action) { described_class.new(env) }
8
+
9
+ before do
10
+ action.stub(:debug)
11
+ end
12
+
13
+ describe "#run" do
14
+
15
+ describe "behavior" do
16
+
17
+ after do
18
+ action.run
19
+ end
20
+
21
+ describe "clearing the cache path" do
22
+
23
+ before do
24
+ action.stub(:clean_install_path)
25
+ action.stub(:clean_lockfile_path)
26
+ end
27
+
28
+ context "when the cache path is missing" do
29
+ before do
30
+ env.stub_chain(:cache_path, :exist?) { false }
31
+ end
32
+
33
+ it "should not try to clear the cache path" do
34
+ env.cache_path.should_receive(:rmtree).never
35
+ end
36
+ end
37
+
38
+ context "when the cache path is present" do
39
+ before do
40
+ env.stub_chain(:cache_path, :exist?) { true }
41
+ end
42
+
43
+ it "should try to clear the cache path" do
44
+ env.cache_path.should_receive(:rmtree).exactly(:once)
45
+ end
46
+ end
47
+
48
+ end
49
+
50
+ describe "clearing the install path" do
51
+
52
+ before do
53
+ action.stub(:clean_cache_path)
54
+ action.stub(:clean_lockfile_path)
55
+ end
56
+
57
+ context "when the install path is missing" do
58
+ before do
59
+ env.stub_chain(:install_path, :exist?) { false }
60
+ end
61
+
62
+ it "should not try to clear the install path" do
63
+ env.install_path.should_receive(:children).never
64
+ end
65
+ end
66
+
67
+ context "when the install path is present" do
68
+ before do
69
+ env.stub_chain(:install_path, :exist?) { true }
70
+ end
71
+
72
+ it "should try to clear the install path" do
73
+ children = [mock, mock, mock]
74
+ children.each do |child|
75
+ child.stub(:file?) { false }
76
+ end
77
+ env.stub_chain(:install_path, :children) { children }
78
+
79
+ children.each do |child|
80
+ child.should_receive(:rmtree).exactly(:once)
81
+ end
82
+ end
83
+
84
+ it "should only try to clear out directories from the install path, not files" do
85
+ children = [mock(:file? => false), mock(:file? => true), mock(:file? => true)]
86
+ env.stub_chain(:install_path, :children) { children }
87
+
88
+ children.select(&:file?).each do |child|
89
+ child.should_receive(:rmtree).never
90
+ end
91
+ children.reject(&:file?).each do |child|
92
+ child.should_receive(:rmtree).exactly(:once)
93
+ end
94
+ end
95
+ end
96
+
97
+ end
98
+
99
+ describe "clearing the lockfile path" do
100
+
101
+ before do
102
+ action.stub(:clean_cache_path)
103
+ action.stub(:clean_install_path)
104
+ end
105
+
106
+ context "when the lockfile path is missing" do
107
+ before do
108
+ env.stub_chain(:lockfile_path, :exist?) { false }
109
+ end
110
+
111
+ it "should not try to clear the lockfile path" do
112
+ env.lockfile_path.should_receive(:rmtree).never
113
+ end
114
+ end
115
+
116
+ context "when the lockfile path is present" do
117
+ before do
118
+ env.stub_chain(:lockfile_path, :exist?) { true }
119
+ end
120
+
121
+ it "should try to clear the lockfile path" do
122
+ env.lockfile_path.should_receive(:rmtree).exactly(:once)
123
+ end
124
+ end
125
+
126
+ end
127
+
128
+ end
129
+
130
+ end
131
+
132
+ end
133
+ end
@@ -0,0 +1,37 @@
1
+ require "tmpdir"
2
+
3
+ require "librarian/error"
4
+ require "librarian/action/ensure"
5
+
6
+ module Librarian
7
+ describe Action::Ensure do
8
+
9
+ let(:env) { mock }
10
+ let(:action) { described_class.new(env) }
11
+
12
+ before do
13
+ env.stub(:specfile_name) { "Specfile" }
14
+ end
15
+
16
+ describe "#run" do
17
+
18
+ context "when the environment does not know its project path" do
19
+ before { env.stub(:project_path) { nil } }
20
+
21
+ it "should raise an error describing that the specfile is mising" do
22
+ expect { action.run }.to raise_error(Error, "Cannot find Specfile!")
23
+ end
24
+ end
25
+
26
+ context "when the environment knows its project path" do
27
+ before { env.stub(:project_path) { Dir.tmpdir } }
28
+
29
+ it "should not raise an error" do
30
+ expect { action.run }.to_not raise_error
31
+ end
32
+ end
33
+
34
+ end
35
+
36
+ end
37
+ end
@@ -0,0 +1,113 @@
1
+ require "librarian/error"
2
+ require "librarian/action/install"
3
+
4
+ module Librarian
5
+ describe Action::Install do
6
+
7
+ let(:env) { mock(:specfile_name => "Specfile", :lockfile_name => "Specfile.lock") }
8
+ let(:action) { described_class.new(env) }
9
+
10
+ describe "#run" do
11
+
12
+ describe "behavior" do
13
+
14
+ describe "checking preconditions" do
15
+
16
+ context "when the specfile is missing" do
17
+ before do
18
+ env.stub_chain(:specfile_path, :exist?) { false }
19
+ end
20
+
21
+ it "should raise an error explaining that the specfile is missing" do
22
+ expect { action.run }.to raise_error(Error, "Specfile missing!")
23
+ end
24
+ end
25
+
26
+ context "when the specfile is present but the lockfile is missing" do
27
+ before do
28
+ env.stub_chain(:specfile_path, :exist?) { true }
29
+ env.stub_chain(:lockfile_path, :exist?) { false }
30
+ end
31
+
32
+ it "should raise an error explaining that the lockfile is missing" do
33
+ expect { action.run }.to raise_error(Error, "Specfile.lock missing!")
34
+ end
35
+ end
36
+
37
+ context "when the specfile and lockfile are present but inconsistent" do
38
+ before do
39
+ env.stub_chain(:specfile_path, :exist?) { true }
40
+ env.stub_chain(:lockfile_path, :exist?) { true }
41
+ action.stub(:spec_consistent_with_lock?) { false }
42
+ end
43
+
44
+ it "should raise an error explaining the inconsistenty" do
45
+ expect { action.run }.to raise_error(Error, "Specfile and Specfile.lock are out of sync!")
46
+ end
47
+ end
48
+
49
+ context "when the specfile and lockfile are present and consistent" do
50
+ before do
51
+ env.stub_chain(:specfile_path, :exist?) { true }
52
+ env.stub_chain(:lockfile_path, :exist?) { true }
53
+ action.stub(:spec_consistent_with_lock?) { true }
54
+ action.stub(:perform_installation)
55
+ end
56
+
57
+ it "should not raise an error" do
58
+ expect { action.run }.to_not raise_error
59
+ end
60
+ end
61
+
62
+ end
63
+
64
+ describe "performing the install" do
65
+
66
+ let(:manifests) { [mock, mock, mock] }
67
+ let(:sorted_manifests) { [mock, mock, mock, mock] }
68
+ let(:install_path) { mock }
69
+
70
+ before do
71
+ env.stub(:install_path) { install_path }
72
+ action.stub(:check_preconditions)
73
+ action.stub_chain(:lock, :manifests) { manifests }
74
+ end
75
+
76
+ after do
77
+ action.run
78
+ end
79
+
80
+ it "should sort, cache, and install the manifests" do
81
+ ManifestSet.should_receive(:sort).with(manifests).exactly(:once).ordered { sorted_manifests }
82
+
83
+ sorted_manifests.each do |manifest|
84
+ source = mock
85
+ manifest.stub(:source) { source }
86
+ source.should_receive(:cache!).with([manifest]).exactly(:once).ordered
87
+ end
88
+
89
+ install_path.stub(:exist?) { false }
90
+ install_path.should_receive(:mkpath).exactly(:once).ordered
91
+
92
+ sorted_manifests.each do |manifest|
93
+ manifest.should_receive(:install!).exactly(:once).ordered
94
+ end
95
+ end
96
+
97
+ it "should not try to create the install path if it already exists" do
98
+ action.stub(:sorted_manifests) { sorted_manifests }
99
+ action.stub(:cache_manifests)
100
+ action.stub(:install_manifests)
101
+
102
+ install_path.stub(:exist?) { true }
103
+ install_path.should_not_receive(:mkpath)
104
+ end
105
+
106
+ end
107
+
108
+ end
109
+
110
+ end
111
+
112
+ end
113
+ end