librarian 0.1.1 → 0.1.2
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.
- 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
|