librarian 0.1.1 → 0.1.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (41) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +1 -2
  3. data/CHANGELOG.md +15 -0
  4. data/Gemfile +2 -0
  5. data/VERSION +1 -0
  6. data/lib/librarian/algorithms.rb +133 -0
  7. data/lib/librarian/cli/manifest_presenter.rb +1 -5
  8. data/lib/librarian/dependency.rb +7 -1
  9. data/lib/librarian/environment.rb +20 -2
  10. data/lib/librarian/environment/runtime_cache.rb +101 -0
  11. data/lib/librarian/manifest.rb +7 -1
  12. data/lib/librarian/manifest_set.rb +11 -12
  13. data/lib/librarian/posix.rb +14 -5
  14. data/lib/librarian/resolver.rb +22 -9
  15. data/lib/librarian/resolver/implementation.rb +64 -49
  16. data/lib/librarian/source/git.rb +47 -11
  17. data/lib/librarian/source/git/repository.rb +33 -3
  18. data/lib/librarian/version.rb +1 -1
  19. data/librarian.gemspec +8 -6
  20. data/spec/functional/cli_spec.rb +1 -1
  21. data/spec/functional/posix_spec.rb +6 -8
  22. data/spec/functional/source/git/repository_spec.rb +55 -27
  23. data/spec/functional/source/git_spec.rb +152 -8
  24. data/spec/support/project_path_macro.rb +14 -0
  25. data/spec/unit/action/base_spec.rb +1 -1
  26. data/spec/unit/action/clean_spec.rb +6 -6
  27. data/spec/unit/action/install_spec.rb +5 -5
  28. data/spec/unit/algorithms_spec.rb +131 -0
  29. data/spec/unit/config/database_spec.rb +38 -38
  30. data/spec/unit/dependency/requirement_spec.rb +12 -0
  31. data/spec/unit/dsl_spec.rb +49 -49
  32. data/spec/unit/environment/runtime_cache_spec.rb +73 -0
  33. data/spec/unit/environment_spec.rb +28 -28
  34. data/spec/unit/lockfile/parser_spec.rb +18 -18
  35. data/spec/unit/lockfile_spec.rb +3 -3
  36. data/spec/unit/manifest/version_spec.rb +11 -0
  37. data/spec/unit/manifest_set_spec.rb +20 -20
  38. data/spec/unit/mock/environment_spec.rb +4 -4
  39. data/spec/unit/resolver_spec.rb +61 -20
  40. data/spec/unit/spec_change_set_spec.rb +19 -19
  41. metadata +19 -5
@@ -15,7 +15,7 @@ module Librarian
15
15
  end
16
16
 
17
17
  it "should print the version" do
18
- stdout.should == strip_heredoc(<<-STDOUT)
18
+ expect(stdout).to eq strip_heredoc(<<-STDOUT)
19
19
  librarian-#{Librarian::VERSION}
20
20
  librarian-mock-#{Librarian::Mock::VERSION}
21
21
  STDOUT
@@ -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.should be == "hello there"
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.should be == tmp_path.to_s
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.should be == "KOALA=BEAR"
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) do
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.should_not be_empty }
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.should =~ /^\d+(\.\d+)+$/ }
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.should be_git
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.should be_empty
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.should be_empty
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.should be == [String]
94
- shas.map(&:size).uniq.should be == [40]
95
- shas.uniq.should be == shas
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.should be_git
107
+ expect(subject).to be_git
110
108
  end
111
109
 
112
110
  it "should have a single remote for it" do
113
- subject.should have(1).remote_names
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.should == "origin"
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"].should include branch
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.should be_checked_out(master_sha)
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.should be_checked_out(branch_sha)
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.should_not be_checked_out(master_sha)
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.should be_checked_out(tag_sha)
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.should_not be_checked_out(master_sha)
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.should be_checked_out(atag_sha)
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.should_not be_checked_out(master_sha)
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(:cache_path) { tmp_path + "cache" }
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(:logger) { double(:debug => nil, :info => nil) }
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
@@ -11,7 +11,7 @@ module Librarian
11
11
  it { should respond_to :environment }
12
12
 
13
13
  it "should have the environment that was assigned to it" do
14
- action.environment.should be env
14
+ expect(action.environment).to be env
15
15
  end
16
16
 
17
17
  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.should_receive(:rmtree).never
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.should_receive(:rmtree).exactly(:once)
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.should_receive(:children).never
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.should_receive(:rmtree).exactly(:once)
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.should_receive(:rmtree).never
87
+ expect(child).to receive(:rmtree).never
88
88
  end
89
89
  children.reject(&:file?).each do |child|
90
- child.should_receive(:rmtree).exactly(:once)
90
+ expect(child).to receive(:rmtree).exactly(:once)
91
91
  end
92
92
  end
93
93
  end