librarian 0.1.1 → 0.1.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +1 -2
- data/CHANGELOG.md +15 -0
- data/Gemfile +2 -0
- data/VERSION +1 -0
- data/lib/librarian/algorithms.rb +133 -0
- data/lib/librarian/cli/manifest_presenter.rb +1 -5
- data/lib/librarian/dependency.rb +7 -1
- data/lib/librarian/environment.rb +20 -2
- data/lib/librarian/environment/runtime_cache.rb +101 -0
- data/lib/librarian/manifest.rb +7 -1
- data/lib/librarian/manifest_set.rb +11 -12
- data/lib/librarian/posix.rb +14 -5
- data/lib/librarian/resolver.rb +22 -9
- data/lib/librarian/resolver/implementation.rb +64 -49
- data/lib/librarian/source/git.rb +47 -11
- data/lib/librarian/source/git/repository.rb +33 -3
- data/lib/librarian/version.rb +1 -1
- data/librarian.gemspec +8 -6
- data/spec/functional/cli_spec.rb +1 -1
- data/spec/functional/posix_spec.rb +6 -8
- data/spec/functional/source/git/repository_spec.rb +55 -27
- data/spec/functional/source/git_spec.rb +152 -8
- data/spec/support/project_path_macro.rb +14 -0
- data/spec/unit/action/base_spec.rb +1 -1
- data/spec/unit/action/clean_spec.rb +6 -6
- data/spec/unit/action/install_spec.rb +5 -5
- data/spec/unit/algorithms_spec.rb +131 -0
- data/spec/unit/config/database_spec.rb +38 -38
- data/spec/unit/dependency/requirement_spec.rb +12 -0
- data/spec/unit/dsl_spec.rb +49 -49
- data/spec/unit/environment/runtime_cache_spec.rb +73 -0
- data/spec/unit/environment_spec.rb +28 -28
- data/spec/unit/lockfile/parser_spec.rb +18 -18
- data/spec/unit/lockfile_spec.rb +3 -3
- data/spec/unit/manifest/version_spec.rb +11 -0
- data/spec/unit/manifest_set_spec.rb +20 -20
- data/spec/unit/mock/environment_spec.rb +4 -4
- data/spec/unit/resolver_spec.rb +61 -20
- data/spec/unit/spec_change_set_spec.rb +19 -19
- metadata +19 -5
data/spec/functional/cli_spec.rb
CHANGED
@@ -1,12 +1,10 @@
|
|
1
1
|
require "librarian/posix"
|
2
2
|
|
3
|
+
require "support/project_path_macro"
|
4
|
+
|
3
5
|
describe Librarian::Posix do
|
6
|
+
include Support::ProjectPathMacro
|
4
7
|
|
5
|
-
let(:project_path) do
|
6
|
-
project_path = Pathname.new(__FILE__).expand_path
|
7
|
-
project_path = project_path.dirname until project_path.join("Rakefile").exist?
|
8
|
-
project_path
|
9
|
-
end
|
10
8
|
let(:tmp_path) { project_path + "tmp/spec/functional/posix" }
|
11
9
|
after { tmp_path.rmtree if tmp_path && tmp_path.exist? }
|
12
10
|
|
@@ -14,19 +12,19 @@ describe Librarian::Posix do
|
|
14
12
|
|
15
13
|
it "returns the stdout" do
|
16
14
|
res = described_class.run!(%w[echo hello there]).strip
|
17
|
-
res.
|
15
|
+
expect(res).to eq "hello there"
|
18
16
|
end
|
19
17
|
|
20
18
|
it "changes directory" do
|
21
19
|
tmp_path.mkpath
|
22
20
|
res = described_class.run!(%w[pwd], :chdir => tmp_path).strip
|
23
|
-
res.
|
21
|
+
expect(res).to eq tmp_path.to_s
|
24
22
|
end
|
25
23
|
|
26
24
|
it "reads the env" do
|
27
25
|
res = described_class.run!(%w[env], :env => {"KOALA" => "BEAR"})
|
28
26
|
line = res.lines.find{|l| l.start_with?("KOALA=")}.strip
|
29
|
-
line.
|
27
|
+
expect(line).to eq "KOALA=BEAR"
|
30
28
|
end
|
31
29
|
|
32
30
|
end
|
@@ -6,17 +6,15 @@ require "librarian/posix"
|
|
6
6
|
|
7
7
|
require "librarian/source/git/repository"
|
8
8
|
|
9
|
+
require "librarian/mock/environment"
|
10
|
+
|
11
|
+
require "support/project_path_macro"
|
12
|
+
|
9
13
|
describe Librarian::Source::Git::Repository do
|
14
|
+
include Support::ProjectPathMacro
|
10
15
|
|
11
|
-
let(:env)
|
12
|
-
double(:ui => nil, :logger => double(:debug => nil, :info => nil))
|
13
|
-
end
|
16
|
+
let(:env) { Librarian::Mock::Environment.new }
|
14
17
|
|
15
|
-
let(:project_path) do
|
16
|
-
project_path = Pathname.new(__FILE__).expand_path
|
17
|
-
project_path = project_path.dirname until project_path.join("Rakefile").exist?
|
18
|
-
project_path
|
19
|
-
end
|
20
18
|
let(:tmp_path) { project_path + "tmp/spec/functional/source/git/repository" }
|
21
19
|
after { tmp_path.rmtree if tmp_path && tmp_path.exist? }
|
22
20
|
let(:git_source_path) { tmp_path + SecureRandom.hex(16) }
|
@@ -64,35 +62,35 @@ describe Librarian::Source::Git::Repository do
|
|
64
62
|
end
|
65
63
|
|
66
64
|
describe ".bin" do
|
67
|
-
specify { described_class.bin.
|
65
|
+
specify { expect(described_class.bin).to_not be_empty }
|
68
66
|
end
|
69
67
|
|
70
68
|
describe ".git_version" do
|
71
|
-
specify { described_class.git_version.
|
69
|
+
specify { expect(described_class.git_version).to match( /^\d+(\.\d+)+$/ ) }
|
72
70
|
end
|
73
71
|
|
74
72
|
context "the original" do
|
75
73
|
subject { described_class.new(env, git_source_path) }
|
76
74
|
|
77
75
|
it "should recognize it" do
|
78
|
-
subject.
|
76
|
+
expect(subject).to be_git
|
79
77
|
end
|
80
78
|
|
81
79
|
it "should not list any remotes for it" do
|
82
|
-
subject.remote_names.
|
80
|
+
expect(subject.remote_names).to be_empty
|
83
81
|
end
|
84
82
|
|
85
83
|
it "should not list any remote branches for it" do
|
86
|
-
subject.remote_branch_names.
|
84
|
+
expect(subject.remote_branch_names).to be_empty
|
87
85
|
end
|
88
86
|
|
89
87
|
it "should have divergent shas for master, branch, tag, and atag" do
|
90
88
|
revs = %W[ master #{branch} #{tag} #{atag} ]
|
91
89
|
rev_parse = proc{|rev| git!(%W[rev-parse #{rev} --quiet]).strip}
|
92
90
|
shas = Dir.chdir(git_source_path){revs.map(&rev_parse)}
|
93
|
-
shas.map(&:class).uniq.
|
94
|
-
shas.map(&:size).uniq.
|
95
|
-
shas.uniq.
|
91
|
+
expect(shas.map(&:class).uniq).to eq [String]
|
92
|
+
expect(shas.map(&:size).uniq).to eq [40]
|
93
|
+
expect(shas.uniq).to eq shas
|
96
94
|
end
|
97
95
|
end
|
98
96
|
|
@@ -106,23 +104,53 @@ describe Librarian::Source::Git::Repository do
|
|
106
104
|
let(:atag_sha) { subject.hash_from("origin", atag) }
|
107
105
|
|
108
106
|
it "should recognize it" do
|
109
|
-
subject.
|
107
|
+
expect(subject).to be_git
|
110
108
|
end
|
111
109
|
|
112
110
|
it "should have a single remote for it" do
|
113
|
-
subject.
|
111
|
+
expect(subject).to have(1).remote_names
|
114
112
|
end
|
115
113
|
|
116
114
|
it "should have a remote with the expected name" do
|
117
|
-
subject.remote_names.first.
|
115
|
+
expect(subject.remote_names.first).to eq "origin"
|
118
116
|
end
|
119
117
|
|
120
118
|
it "should have the remote branch" do
|
121
|
-
subject.remote_branch_names["origin"].
|
119
|
+
expect(subject.remote_branch_names["origin"]).to include branch
|
122
120
|
end
|
123
121
|
|
124
122
|
it "should be checked out on the master" do
|
125
|
-
subject.
|
123
|
+
expect(subject).to be_checked_out(master_sha)
|
124
|
+
end
|
125
|
+
|
126
|
+
context "checking for commits" do
|
127
|
+
it "has the master commit" do
|
128
|
+
expect(subject).to have_commit(master_sha)
|
129
|
+
end
|
130
|
+
|
131
|
+
it "has the branch commit" do
|
132
|
+
expect(subject).to have_commit(branch_sha)
|
133
|
+
end
|
134
|
+
|
135
|
+
it "has the tag commit" do
|
136
|
+
expect(subject).to have_commit(tag_sha)
|
137
|
+
end
|
138
|
+
|
139
|
+
it "has the atag commit" do
|
140
|
+
expect(subject).to have_commit(atag_sha)
|
141
|
+
end
|
142
|
+
|
143
|
+
it "does not have a made-up commit" do
|
144
|
+
expect(subject).to_not have_commit(SecureRandom.hex(20))
|
145
|
+
end
|
146
|
+
|
147
|
+
it "does not have a tree commit" do
|
148
|
+
master_tree_sha = Dir.chdir(git_source_path) do
|
149
|
+
git!(%W[log -1 --no-color --format=tformat:%T master]).strip
|
150
|
+
end
|
151
|
+
expect(master_tree_sha).to match(/\A[0-9a-f]{40}\z/) # sanity
|
152
|
+
expect(subject).to_not have_commit(master_tree_sha)
|
153
|
+
end
|
126
154
|
end
|
127
155
|
|
128
156
|
context "checking out the branch" do
|
@@ -131,11 +159,11 @@ describe Librarian::Source::Git::Repository do
|
|
131
159
|
end
|
132
160
|
|
133
161
|
it "should be checked out on the branch" do
|
134
|
-
subject.
|
162
|
+
expect(subject).to be_checked_out(branch_sha)
|
135
163
|
end
|
136
164
|
|
137
165
|
it "should not be checked out on the master" do
|
138
|
-
subject.
|
166
|
+
expect(subject).to_not be_checked_out(master_sha)
|
139
167
|
end
|
140
168
|
end
|
141
169
|
|
@@ -145,11 +173,11 @@ describe Librarian::Source::Git::Repository do
|
|
145
173
|
end
|
146
174
|
|
147
175
|
it "should be checked out on the tag" do
|
148
|
-
subject.
|
176
|
+
expect(subject).to be_checked_out(tag_sha)
|
149
177
|
end
|
150
178
|
|
151
179
|
it "should not be checked out on the master" do
|
152
|
-
subject.
|
180
|
+
expect(subject).to_not be_checked_out(master_sha)
|
153
181
|
end
|
154
182
|
end
|
155
183
|
|
@@ -159,11 +187,11 @@ describe Librarian::Source::Git::Repository do
|
|
159
187
|
end
|
160
188
|
|
161
189
|
it "should be checked out on the annotated tag" do
|
162
|
-
subject.
|
190
|
+
expect(subject).to be_checked_out(atag_sha)
|
163
191
|
end
|
164
192
|
|
165
193
|
it "should not be checked out on the master" do
|
166
|
-
subject.
|
194
|
+
expect(subject).to_not be_checked_out(master_sha)
|
167
195
|
end
|
168
196
|
end
|
169
197
|
end
|
@@ -1,24 +1,37 @@
|
|
1
|
+
require "fileutils"
|
1
2
|
require "pathname"
|
2
3
|
require "securerandom"
|
3
4
|
|
4
5
|
require "librarian/error"
|
6
|
+
require "librarian/posix"
|
5
7
|
require "librarian/source/git"
|
8
|
+
require "librarian/source/git/repository"
|
9
|
+
require "librarian/mock/environment"
|
10
|
+
|
11
|
+
require "support/project_path_macro"
|
6
12
|
|
7
13
|
describe Librarian::Source::Git do
|
14
|
+
include Support::ProjectPathMacro
|
8
15
|
|
9
|
-
let(:project_path) do
|
10
|
-
project_path = Pathname.new(__FILE__).expand_path
|
11
|
-
project_path = project_path.dirname until project_path.join("Rakefile").exist?
|
12
|
-
project_path
|
13
|
-
end
|
14
16
|
let(:tmp_path) { project_path + "tmp/spec/functional/source/git" }
|
15
17
|
after { tmp_path.rmtree if tmp_path && tmp_path.exist? }
|
16
|
-
let(:
|
18
|
+
let(:env_project_path) { tmp_path + "project" }
|
19
|
+
|
20
|
+
def cmd!(command)
|
21
|
+
Librarian::Posix.run! command
|
22
|
+
end
|
23
|
+
|
24
|
+
def git!(command)
|
25
|
+
cmd!([Librarian::Source::Git::Repository.bin] + command)
|
26
|
+
end
|
27
|
+
|
28
|
+
def new_env
|
29
|
+
Librarian::Mock::Environment.new(:project_path => env_project_path)
|
30
|
+
end
|
17
31
|
|
18
32
|
context "when the remote is bad" do
|
19
33
|
let(:remote) { tmp_path.join(SecureRandom.hex(8)).to_s }
|
20
|
-
let(:
|
21
|
-
let(:env) { double(:ui => nil, :logger => logger, :cache_path => cache_path) }
|
34
|
+
let(:env) { new_env }
|
22
35
|
let(:source) { described_class.new(env, remote, {}) }
|
23
36
|
|
24
37
|
it "fails when caching" do
|
@@ -27,4 +40,135 @@ describe Librarian::Source::Git do
|
|
27
40
|
end
|
28
41
|
end
|
29
42
|
|
43
|
+
context "when the remote has a repo" do
|
44
|
+
let(:remote) { tmp_path.join(SecureRandom.hex(8)).to_s }
|
45
|
+
let(:git_source_path) { Pathname.new(remote) }
|
46
|
+
let(:env) { new_env }
|
47
|
+
let(:source) { described_class.new(env, remote, {}) }
|
48
|
+
|
49
|
+
before do
|
50
|
+
git_source_path.mkpath
|
51
|
+
Dir.chdir(git_source_path) do
|
52
|
+
git! %W[init]
|
53
|
+
git! %W[config user.name Simba]
|
54
|
+
git! %W[config user.email simba@savannah-pride.gov]
|
55
|
+
FileUtils.touch "butter.txt"
|
56
|
+
git! %W[add butter.txt]
|
57
|
+
git! %W[commit -m #{"Initial Commit"}]
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
let(:sha) do
|
62
|
+
Dir.chdir(git_source_path) do
|
63
|
+
git!(%W[rev-parse master]).strip
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
context "when caching once" do
|
68
|
+
it "has the expected sha" do
|
69
|
+
expect{source.cache!}.to change{source.sha}.from(nil).to(sha)
|
70
|
+
end
|
71
|
+
|
72
|
+
it "records the history" do
|
73
|
+
expect{source.cache!}.to change{source.git_ops_count}.from(0).to(9)
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
context "when caching twice" do
|
78
|
+
before { source.cache! }
|
79
|
+
|
80
|
+
it "keeps the expected sha" do
|
81
|
+
expect{source.cache!}.to_not change{source.sha}
|
82
|
+
end
|
83
|
+
|
84
|
+
it "runs git commands once" do
|
85
|
+
expect{source.cache!}.to_not change{source.git_ops_count}
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
context "when caching twice from different sources" do
|
90
|
+
let(:other_source) { described_class.new(env, remote, {}) }
|
91
|
+
before { other_source.cache! }
|
92
|
+
|
93
|
+
it "has the expected sha" do
|
94
|
+
expect{source.cache!}.to change{source.sha}.from(nil).to(sha)
|
95
|
+
end
|
96
|
+
|
97
|
+
it "records the history" do
|
98
|
+
expect{source.cache!}.to change{source.git_ops_count}.from(0).to(1)
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
context "when caching twice from different sources, second time with sha" do
|
103
|
+
let(:other_source) { described_class.new(env, remote, {}) }
|
104
|
+
before { other_source.cache! }
|
105
|
+
|
106
|
+
let(:source) { described_class.new(env, remote, {:sha => sha}) }
|
107
|
+
|
108
|
+
it "has the expected sha" do
|
109
|
+
expect{source.cache!}.to_not change{source.sha}
|
110
|
+
end
|
111
|
+
|
112
|
+
it "records the history" do
|
113
|
+
expect{source.cache!}.to change{source.git_ops_count}.from(0).to(1)
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
context "when caching twice from different environments" do
|
118
|
+
let(:other_source) { described_class.new(new_env, remote, {}) }
|
119
|
+
before { other_source.cache! }
|
120
|
+
|
121
|
+
it "has the expected sha" do
|
122
|
+
expect{source.cache!}.to change{source.sha}.from(nil).to(sha)
|
123
|
+
end
|
124
|
+
|
125
|
+
it "records the history" do
|
126
|
+
expect{source.cache!}.to change{source.git_ops_count}.from(0).to(8)
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
context "when caching twice from different environments, second time with sha" do
|
131
|
+
let(:other_source) { described_class.new(new_env, remote, {}) }
|
132
|
+
before { other_source.cache! }
|
133
|
+
|
134
|
+
let(:source) { described_class.new(env, remote, {:sha => sha}) }
|
135
|
+
|
136
|
+
it "has the expected sha" do
|
137
|
+
expect{source.cache!}.to_not change{source.sha}
|
138
|
+
end
|
139
|
+
|
140
|
+
it "records the history" do
|
141
|
+
expect{source.cache!}.to change{source.git_ops_count}.from(0).to(3)
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
context "when the sha is missing from a cached repo" do
|
146
|
+
let(:other_source) { described_class.new(new_env, remote, {}) }
|
147
|
+
before { other_source.cache! }
|
148
|
+
|
149
|
+
before do
|
150
|
+
Dir.chdir(git_source_path) do
|
151
|
+
FileUtils.touch "jam.txt"
|
152
|
+
git! %w[add jam.txt]
|
153
|
+
git! %W[commit -m #{"Some Jam"}]
|
154
|
+
end
|
155
|
+
end
|
156
|
+
|
157
|
+
let(:source) { described_class.new(env, remote, {:sha => sha}) }
|
158
|
+
|
159
|
+
it "has a new remote sha" do
|
160
|
+
expect(sha).to_not eq(other_source.sha)
|
161
|
+
end
|
162
|
+
|
163
|
+
it "has the expected sha" do
|
164
|
+
expect{source.cache!}.to_not change{source.sha}
|
165
|
+
end
|
166
|
+
|
167
|
+
it "records the history" do
|
168
|
+
expect{source.cache!}.to change{source.git_ops_count}.from(0).to(8)
|
169
|
+
end
|
170
|
+
end
|
171
|
+
|
172
|
+
end
|
173
|
+
|
30
174
|
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
module Support
|
2
|
+
module ProjectPathMacro
|
3
|
+
|
4
|
+
project_path = Pathname.new(__FILE__).expand_path
|
5
|
+
project_path = project_path.dirname until project_path.join("Rakefile").exist?
|
6
|
+
|
7
|
+
PROJECT_PATH = project_path
|
8
|
+
|
9
|
+
def project_path
|
10
|
+
PROJECT_PATH
|
11
|
+
end
|
12
|
+
|
13
|
+
end
|
14
|
+
end
|
@@ -30,7 +30,7 @@ module Librarian
|
|
30
30
|
end
|
31
31
|
|
32
32
|
it "should not try to clear the cache path" do
|
33
|
-
env.cache_path.
|
33
|
+
expect(env.cache_path).to receive(:rmtree).never
|
34
34
|
end
|
35
35
|
end
|
36
36
|
|
@@ -40,7 +40,7 @@ module Librarian
|
|
40
40
|
end
|
41
41
|
|
42
42
|
it "should try to clear the cache path" do
|
43
|
-
env.cache_path.
|
43
|
+
expect(env.cache_path).to receive(:rmtree).exactly(:once)
|
44
44
|
end
|
45
45
|
end
|
46
46
|
|
@@ -58,7 +58,7 @@ module Librarian
|
|
58
58
|
end
|
59
59
|
|
60
60
|
it "should not try to clear the install path" do
|
61
|
-
env.install_path.
|
61
|
+
expect(env.install_path).to receive(:children).never
|
62
62
|
end
|
63
63
|
end
|
64
64
|
|
@@ -75,7 +75,7 @@ module Librarian
|
|
75
75
|
env.stub_chain(:install_path, :children) { children }
|
76
76
|
|
77
77
|
children.each do |child|
|
78
|
-
child.
|
78
|
+
expect(child).to receive(:rmtree).exactly(:once)
|
79
79
|
end
|
80
80
|
end
|
81
81
|
|
@@ -84,10 +84,10 @@ module Librarian
|
|
84
84
|
env.stub_chain(:install_path, :children) { children }
|
85
85
|
|
86
86
|
children.select(&:file?).each do |child|
|
87
|
-
child.
|
87
|
+
expect(child).to receive(:rmtree).never
|
88
88
|
end
|
89
89
|
children.reject(&:file?).each do |child|
|
90
|
-
child.
|
90
|
+
expect(child).to receive(:rmtree).exactly(:once)
|
91
91
|
end
|
92
92
|
end
|
93
93
|
end
|