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.
- data/CHANGELOG.md +4 -0
- data/lib/librarian.rb +5 -178
- data/lib/librarian/action.rb +5 -0
- data/lib/librarian/action/base.rb +22 -0
- data/lib/librarian/action/clean.rb +56 -0
- data/lib/librarian/action/ensure.rb +24 -0
- data/lib/librarian/action/install.rb +101 -0
- data/lib/librarian/action/resolve.rb +81 -0
- data/lib/librarian/action/update.rb +76 -0
- data/lib/librarian/chef/cli.rb +7 -2
- data/lib/librarian/chef/dsl.rb +0 -3
- data/lib/librarian/chef/environment.rb +19 -0
- data/lib/librarian/chef/extension.rb +1 -16
- data/lib/librarian/chef/integration/knife.rb +9 -16
- data/lib/librarian/chef/source/git.rb +0 -2
- data/lib/librarian/chef/source/local.rb +1 -74
- data/lib/librarian/chef/source/local/manifest.rb +82 -0
- data/lib/librarian/chef/source/path.rb +0 -2
- data/lib/librarian/chef/source/site.rb +9 -89
- data/lib/librarian/chef/source/site/manifest.rb +94 -0
- data/lib/librarian/cli.rb +56 -17
- data/lib/librarian/dependency.rb +2 -2
- data/lib/librarian/dsl.rb +15 -5
- data/lib/librarian/dsl/receiver.rb +2 -0
- data/lib/librarian/dsl/target.rb +13 -1
- data/lib/librarian/environment.rb +94 -0
- data/lib/librarian/error.rb +4 -0
- data/lib/librarian/helpers/debug.rb +6 -6
- data/lib/librarian/lockfile.rb +7 -5
- data/lib/librarian/lockfile/compiler.rb +5 -4
- data/lib/librarian/lockfile/parser.rb +6 -5
- data/lib/librarian/manifest.rb +2 -2
- data/lib/librarian/mock/cli.rb +6 -1
- data/lib/librarian/mock/dsl.rb +0 -3
- data/lib/librarian/mock/environment.rb +24 -0
- data/lib/librarian/mock/extension.rb +1 -20
- data/lib/librarian/mock/source/mock.rb +7 -7
- data/lib/librarian/mock/source/mock/registry.rb +16 -12
- data/lib/librarian/resolver.rb +5 -116
- data/lib/librarian/resolver/implementation.rb +117 -0
- data/lib/librarian/source/git.rb +8 -7
- data/lib/librarian/source/git/repository.rb +7 -5
- data/lib/librarian/source/local.rb +1 -1
- data/lib/librarian/source/path.rb +7 -6
- data/lib/librarian/spec_change_set.rb +6 -5
- data/lib/librarian/specfile.rb +10 -4
- data/lib/librarian/version.rb +1 -1
- data/librarian.gemspec +1 -0
- data/spec/functional/chef/source/git_spec.rb +177 -89
- data/spec/functional/chef/source/site_spec.rb +111 -52
- data/spec/unit/action/base_spec.rb +18 -0
- data/spec/unit/action/clean_spec.rb +133 -0
- data/spec/unit/action/ensure_spec.rb +37 -0
- data/spec/unit/action/install_spec.rb +113 -0
- data/spec/unit/dsl_spec.rb +15 -13
- data/spec/unit/environment_spec.rb +9 -0
- data/spec/unit/lockfile_spec.rb +15 -4
- data/spec/unit/mock/source/mock.rb +22 -0
- data/spec/unit/resolver_spec.rb +24 -24
- data/spec/unit/spec_change_set_spec.rb +29 -25
- metadata +47 -19
- data/lib/librarian/chef/particularity.rb +0 -9
- data/lib/librarian/mock/particularity.rb +0 -9
- 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(
|
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
|
-
|
71
|
-
repo_path
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
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
|
-
|
88
|
-
repo_path
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
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
|
-
|
106
|
-
repo_path
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
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
|
-
|
148
|
-
|
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
|