librarianp 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.
Files changed (100) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +5 -0
  3. data/.rspec +1 -0
  4. data/.travis.yml +10 -0
  5. data/CHANGELOG.md +255 -0
  6. data/Gemfile +8 -0
  7. data/Gemfile.lock +235 -0
  8. data/LICENSE.txt +22 -0
  9. data/README.md +55 -0
  10. data/Rakefile +28 -0
  11. data/VERSION +1 -0
  12. data/lib/librarian/action/base.rb +24 -0
  13. data/lib/librarian/action/clean.rb +44 -0
  14. data/lib/librarian/action/ensure.rb +24 -0
  15. data/lib/librarian/action/install.rb +95 -0
  16. data/lib/librarian/action/persist_resolution_mixin.rb +51 -0
  17. data/lib/librarian/action/resolve.rb +46 -0
  18. data/lib/librarian/action/update.rb +44 -0
  19. data/lib/librarian/action.rb +5 -0
  20. data/lib/librarian/algorithms.rb +133 -0
  21. data/lib/librarian/cli/manifest_presenter.rb +89 -0
  22. data/lib/librarian/cli.rb +225 -0
  23. data/lib/librarian/config/database.rb +205 -0
  24. data/lib/librarian/config/file_source.rb +47 -0
  25. data/lib/librarian/config/hash_source.rb +33 -0
  26. data/lib/librarian/config/source.rb +149 -0
  27. data/lib/librarian/config.rb +7 -0
  28. data/lib/librarian/dependency.rb +153 -0
  29. data/lib/librarian/dsl/receiver.rb +42 -0
  30. data/lib/librarian/dsl/target.rb +171 -0
  31. data/lib/librarian/dsl.rb +102 -0
  32. data/lib/librarian/environment/runtime_cache.rb +101 -0
  33. data/lib/librarian/environment.rb +230 -0
  34. data/lib/librarian/error.rb +4 -0
  35. data/lib/librarian/helpers.rb +29 -0
  36. data/lib/librarian/linter/source_linter.rb +55 -0
  37. data/lib/librarian/lockfile/compiler.rb +66 -0
  38. data/lib/librarian/lockfile/parser.rb +123 -0
  39. data/lib/librarian/lockfile.rb +29 -0
  40. data/lib/librarian/logger.rb +46 -0
  41. data/lib/librarian/manifest.rb +146 -0
  42. data/lib/librarian/manifest_set.rb +150 -0
  43. data/lib/librarian/mock/cli.rb +19 -0
  44. data/lib/librarian/mock/dsl.rb +15 -0
  45. data/lib/librarian/mock/environment.rb +21 -0
  46. data/lib/librarian/mock/extension.rb +9 -0
  47. data/lib/librarian/mock/source/mock/registry.rb +83 -0
  48. data/lib/librarian/mock/source/mock.rb +80 -0
  49. data/lib/librarian/mock/source.rb +1 -0
  50. data/lib/librarian/mock/version.rb +5 -0
  51. data/lib/librarian/mock.rb +1 -0
  52. data/lib/librarian/posix.rb +129 -0
  53. data/lib/librarian/resolution.rb +46 -0
  54. data/lib/librarian/resolver/implementation.rb +238 -0
  55. data/lib/librarian/resolver.rb +94 -0
  56. data/lib/librarian/rspec/support/cli_macro.rb +120 -0
  57. data/lib/librarian/source/basic_api.rb +45 -0
  58. data/lib/librarian/source/git/repository.rb +193 -0
  59. data/lib/librarian/source/git.rb +172 -0
  60. data/lib/librarian/source/local.rb +54 -0
  61. data/lib/librarian/source/path.rb +56 -0
  62. data/lib/librarian/source.rb +2 -0
  63. data/lib/librarian/spec.rb +13 -0
  64. data/lib/librarian/spec_change_set.rb +173 -0
  65. data/lib/librarian/specfile.rb +19 -0
  66. data/lib/librarian/support/abstract_method.rb +21 -0
  67. data/lib/librarian/ui.rb +64 -0
  68. data/lib/librarian/version.rb +3 -0
  69. data/lib/librarian.rb +11 -0
  70. data/librarian.gemspec +47 -0
  71. data/spec/functional/cli_spec.rb +27 -0
  72. data/spec/functional/posix_spec.rb +32 -0
  73. data/spec/functional/source/git/repository_spec.rb +199 -0
  74. data/spec/functional/source/git_spec.rb +174 -0
  75. data/spec/support/fakefs.rb +37 -0
  76. data/spec/support/method_patch_macro.rb +30 -0
  77. data/spec/support/project_path_macro.rb +14 -0
  78. data/spec/support/with_env_macro.rb +22 -0
  79. data/spec/unit/action/base_spec.rb +18 -0
  80. data/spec/unit/action/clean_spec.rb +102 -0
  81. data/spec/unit/action/ensure_spec.rb +37 -0
  82. data/spec/unit/action/install_spec.rb +111 -0
  83. data/spec/unit/algorithms_spec.rb +131 -0
  84. data/spec/unit/config/database_spec.rb +320 -0
  85. data/spec/unit/dependency/requirement_spec.rb +12 -0
  86. data/spec/unit/dependency_spec.rb +212 -0
  87. data/spec/unit/dsl_spec.rb +173 -0
  88. data/spec/unit/environment/runtime_cache_spec.rb +73 -0
  89. data/spec/unit/environment_spec.rb +209 -0
  90. data/spec/unit/lockfile/parser_spec.rb +162 -0
  91. data/spec/unit/lockfile_spec.rb +65 -0
  92. data/spec/unit/manifest/version_spec.rb +11 -0
  93. data/spec/unit/manifest_set_spec.rb +202 -0
  94. data/spec/unit/manifest_spec.rb +36 -0
  95. data/spec/unit/mock/environment_spec.rb +25 -0
  96. data/spec/unit/mock/source/mock_spec.rb +22 -0
  97. data/spec/unit/resolver_spec.rb +299 -0
  98. data/spec/unit/source/git_spec.rb +29 -0
  99. data/spec/unit/spec_change_set_spec.rb +169 -0
  100. metadata +257 -0
@@ -0,0 +1,173 @@
1
+ require 'librarian'
2
+ require 'librarian/mock'
3
+
4
+ module Librarian
5
+ module Mock
6
+
7
+ describe Dsl do
8
+
9
+ let(:env) { Environment.new }
10
+
11
+ context "a single source and a single dependency with a blank name" do
12
+ it "should not not run with a blank name" do
13
+ expect do
14
+ env.dsl do
15
+ src 'source-1'
16
+ dep ''
17
+ end
18
+ end.to raise_error(ArgumentError, %{name ("") must be sensible})
19
+ end
20
+ end
21
+
22
+ context "a simple specfile - a single source, a single dependency, no transitive dependencies" do
23
+
24
+ it "should run with a hash source" do
25
+ spec = env.dsl do
26
+ dep 'dependency-1',
27
+ :src => 'source-1'
28
+ end
29
+ expect(spec.dependencies).to_not be_empty
30
+ expect(spec.dependencies.first.name).to eq 'dependency-1'
31
+ expect(spec.dependencies.first.source.name).to eq 'source-1'
32
+ expect(spec.sources).to be_empty
33
+ end
34
+
35
+ it "should run with a shortcut source" do
36
+ spec = env.dsl do
37
+ dep 'dependency-1',
38
+ :source => :a
39
+ end
40
+ expect(spec.dependencies).to_not be_empty
41
+ expect(spec.dependencies.first.name).to eq 'dependency-1'
42
+ expect(spec.dependencies.first.source.name).to eq 'source-a'
43
+ expect(spec.sources).to be_empty
44
+ end
45
+
46
+ it "should run with a block hash source" do
47
+ spec = env.dsl do
48
+ source :src => 'source-1' do
49
+ dep 'dependency-1'
50
+ end
51
+ end
52
+ expect(spec.dependencies).to_not be_empty
53
+ expect(spec.dependencies.first.name).to eq 'dependency-1'
54
+ expect(spec.dependencies.first.source.name).to eq 'source-1'
55
+ expect(spec.sources).to be_empty
56
+ end
57
+
58
+ it "should run with a block named source" do
59
+ spec = env.dsl do
60
+ src 'source-1' do
61
+ dep 'dependency-1'
62
+ end
63
+ end
64
+ expect(spec.dependencies).to_not be_empty
65
+ expect(spec.dependencies.first.name).to eq 'dependency-1'
66
+ expect(spec.dependencies.first.source.name).to eq 'source-1'
67
+ expect(spec.sources).to be_empty
68
+ end
69
+
70
+ it "should run with a default hash source" do
71
+ spec = env.dsl do
72
+ source :src => 'source-1'
73
+ dep 'dependency-1'
74
+ end
75
+ expect(spec.dependencies).to_not be_empty
76
+ expect(spec.dependencies.first.name).to eq 'dependency-1'
77
+ expect(spec.dependencies.first.source.name).to eq 'source-1'
78
+ expect(spec.sources).to_not be_empty
79
+ expect(spec.dependencies.first.source).to eq spec.sources.first
80
+ end
81
+
82
+ it "should run with a default named source" do
83
+ spec = env.dsl do
84
+ src 'source-1'
85
+ dep 'dependency-1'
86
+ end
87
+ expect(spec.dependencies).to_not be_empty
88
+ expect(spec.dependencies.first.name).to eq 'dependency-1'
89
+ expect(spec.dependencies.first.source.name).to eq 'source-1'
90
+ expect(spec.sources).to_not be_empty
91
+ expect(spec.dependencies.first.source).to eq spec.sources.first
92
+ end
93
+
94
+ it "should run with a default shortcut source" do
95
+ spec = env.dsl do
96
+ source :a
97
+ dep 'dependency-1'
98
+ end
99
+ expect(spec.dependencies).to_not be_empty
100
+ expect(spec.dependencies.first.name).to eq 'dependency-1'
101
+ expect(spec.dependencies.first.source.name).to eq 'source-a'
102
+ expect(spec.sources).to_not be_empty
103
+ expect(spec.dependencies.first.source).to eq spec.sources.first
104
+ end
105
+
106
+ it "should run with a shortcut source hash definition" do
107
+ spec = env.dsl do
108
+ source :b, :src => 'source-b'
109
+ dep 'dependency-1', :source => :b
110
+ end
111
+ expect(spec.dependencies).to_not be_empty
112
+ expect(spec.dependencies.first.name).to eq 'dependency-1'
113
+ expect(spec.dependencies.first.source.name).to eq 'source-b'
114
+ expect(spec.sources).to be_empty
115
+ end
116
+
117
+ it "should run with a shortcut source block definition" do
118
+ spec = env.dsl do
119
+ source :b, proc { src 'source-b' }
120
+ dep 'dependency-1', :source => :b
121
+ end
122
+ expect(spec.dependencies).to_not be_empty
123
+ expect(spec.dependencies.first.name).to eq 'dependency-1'
124
+ expect(spec.dependencies.first.source.name).to eq 'source-b'
125
+ expect(spec.sources).to be_empty
126
+ end
127
+
128
+ it "should run with a default shortcut source hash definition" do
129
+ spec = env.dsl do
130
+ source :b, :src => 'source-b'
131
+ source :b
132
+ dep 'dependency-1'
133
+ end
134
+ expect(spec.dependencies).to_not be_empty
135
+ expect(spec.dependencies.first.name).to eq 'dependency-1'
136
+ expect(spec.dependencies.first.source.name).to eq 'source-b'
137
+ expect(spec.sources).to_not be_empty
138
+ expect(spec.sources.first.name).to eq 'source-b'
139
+ end
140
+
141
+ it "should run with a default shortcut source block definition" do
142
+ spec = env.dsl do
143
+ source :b, proc { src 'source-b' }
144
+ source :b
145
+ dep 'dependency-1'
146
+ end
147
+ expect(spec.dependencies).to_not be_empty
148
+ expect(spec.dependencies.first.name).to eq 'dependency-1'
149
+ expect(spec.dependencies.first.source.name).to eq 'source-b'
150
+ expect(spec.sources).to_not be_empty
151
+ expect(spec.sources.first.name).to eq 'source-b'
152
+ end
153
+
154
+ end
155
+
156
+ context "validating source options" do
157
+
158
+ it "should raise when given unrecognized optiosn options" do
159
+ expect do
160
+ env.dsl do
161
+ dep 'dependency-1',
162
+ :src => 'source-1',
163
+ :huh => 'yikes'
164
+ end
165
+ end.to raise_error(Error, %{unrecognized options: huh})
166
+ end
167
+
168
+ end
169
+
170
+ end
171
+
172
+ end
173
+ end
@@ -0,0 +1,73 @@
1
+ require "librarian/environment/runtime_cache"
2
+
3
+ module Librarian
4
+ class Environment
5
+ describe RuntimeCache do
6
+
7
+ let(:rtc) { described_class.new }
8
+ let(:key) { ["brah", "nick"] }
9
+ let(:key_x) { ["brah", "phar"] }
10
+ let(:key_y) { ["rost", "phar"] }
11
+
12
+ def triple(keypair)
13
+ [rtc.include?(*keypair), rtc.get(*keypair), rtc.memo(*keypair){yield}]
14
+ end
15
+
16
+ context "originally" do
17
+ specify { expect(triple(key){9}).to eql([false, nil, 9]) }
18
+ end
19
+
20
+ context "after put" do
21
+ before { rtc.put(*key){6} }
22
+
23
+ specify { expect(triple(key){9}).to eql([true, 6, 6]) }
24
+ specify { expect(triple(key_x){9}).to eql([false, nil, 9]) }
25
+ specify { expect(triple(key_y){9}).to eql([false, nil, 9]) }
26
+ end
27
+
28
+ context "after put then delete" do
29
+ before { rtc.put(*key){6} }
30
+ before { rtc.delete *key }
31
+
32
+ specify { expect(triple(key){9}).to eql([false, nil, 9]) }
33
+ specify { expect(triple(key_x){9}).to eql([false, nil, 9]) }
34
+ specify { expect(triple(key_y){9}).to eql([false, nil, 9]) }
35
+ end
36
+
37
+ context "after memo" do
38
+ before { rtc.memo(*key){6} }
39
+
40
+ specify { expect(triple(key){9}).to eql([true, 6, 6]) }
41
+ specify { expect(triple(key_x){9}).to eql([false, nil, 9]) }
42
+ specify { expect(triple(key_y){9}).to eql([false, nil, 9]) }
43
+ end
44
+
45
+ context "after memo then delete" do
46
+ before { rtc.memo(*key){6} }
47
+ before { rtc.delete *key }
48
+
49
+ specify { expect(triple(key){9}).to eql([false, nil, 9]) }
50
+ specify { expect(triple(key_x){9}).to eql([false, nil, 9]) }
51
+ specify { expect(triple(key_y){9}).to eql([false, nil, 9]) }
52
+ end
53
+
54
+ context "with keyspace wrapper" do
55
+ let(:krtc) { rtc.keyspace("brah") }
56
+ let(:key) { "nick" }
57
+ let(:key_x) { "phar" }
58
+
59
+ def triple(keypair)
60
+ [krtc.include?(key), krtc.get(key), krtc.memo(key){yield}]
61
+ end
62
+
63
+ context "after put" do
64
+ before { krtc.put(key){6} }
65
+
66
+ specify { expect(triple(key){9}).to eql([true, 6, 6]) }
67
+ end
68
+
69
+ end
70
+
71
+ end
72
+ end
73
+ end
@@ -0,0 +1,209 @@
1
+ require "librarian/environment"
2
+
3
+ require "support/with_env_macro"
4
+
5
+ module Librarian
6
+ describe Environment do
7
+ include ::Support::WithEnvMacro
8
+
9
+ let(:env) { described_class.new }
10
+
11
+ describe "#adapter_module" do
12
+ specify { expect(env.adapter_module).to be nil }
13
+ end
14
+
15
+ describe "#adapter_name" do
16
+ specify { expect(env.adapter_name).to be nil }
17
+ end
18
+
19
+ describe "#adapter_version" do
20
+ specify { expect(env.adapter_version).to be nil }
21
+ end
22
+
23
+ describe "computing the home" do
24
+
25
+ context "with the HOME env var" do
26
+ with_env "HOME" => "/path/to/home"
27
+
28
+ it "finds the home" do
29
+ env.stub(:adapter_name).and_return("cat")
30
+ expect(env.config_db.underlying_home.to_s).to eq "/path/to/home"
31
+ end
32
+ end
33
+
34
+ context "without the HOME env var" do
35
+ let!(:real_home) { File.expand_path("~") }
36
+ with_env "HOME" => nil
37
+
38
+ it "finds the home" do
39
+ env.stub(:adapter_name).and_return("cat")
40
+ expect(env.config_db.underlying_home.to_s).to eq real_home
41
+ end
42
+ end
43
+
44
+ end
45
+
46
+ describe "#http_proxy_uri" do
47
+
48
+ context "sanity" do
49
+ with_env "http_proxy" => nil
50
+
51
+ it "should have a nil http proxy uri" do
52
+ expect(env.http_proxy_uri).to be_nil
53
+ end
54
+ end
55
+
56
+ context "with a complex proxy" do
57
+ with_env "http_proxy" => "admin:secret@example.com"
58
+
59
+ it "should have the expcted http proxy uri" do
60
+ expect(env.http_proxy_uri).to eq URI("http://admin:secret@example.com")
61
+ end
62
+
63
+ it "should have the expected host" do
64
+ expect(env.http_proxy_uri.host).to eq "example.com"
65
+ end
66
+
67
+ it "should have the expected user" do
68
+ expect(env.http_proxy_uri.user).to eq "admin"
69
+ end
70
+
71
+ it "should have the expected password" do
72
+ expect(env.http_proxy_uri.password).to eq "secret"
73
+ end
74
+ end
75
+
76
+ context "with a split proxy" do
77
+ with_env "http_proxy" => "example.com",
78
+ "http_proxy_user" => "admin",
79
+ "http_proxy_pass" => "secret"
80
+
81
+ it "should have the expcted http proxy uri" do
82
+ expect(env.http_proxy_uri).to eq URI("http://admin:secret@example.com")
83
+ end
84
+ end
85
+
86
+ end
87
+
88
+ describe "#net_http_class" do
89
+ let(:proxied_host) { "www.example.com" }
90
+ context "sanity" do
91
+ with_env "http_proxy" => nil
92
+
93
+ it "should have the normal class" do
94
+ expect(env.net_http_class(proxied_host)).to be Net::HTTP
95
+ end
96
+
97
+ it "should not be marked as a proxy class" do
98
+ expect(env.net_http_class(proxied_host)).to_not be_proxy_class
99
+ end
100
+ end
101
+
102
+ context "with a complex proxy" do
103
+ with_env "http_proxy" => "admin:secret@example.com"
104
+
105
+ it "should not by marked as a proxy class for localhost" do
106
+ expect(env.net_http_class('localhost')).to_not be_proxy_class
107
+ end
108
+ it "should not have the normal class" do
109
+ expect(env.net_http_class(proxied_host)).to_not be Net::HTTP
110
+ end
111
+
112
+ it "should have a subclass the normal class" do
113
+ expect(env.net_http_class(proxied_host)).to be < Net::HTTP
114
+ end
115
+
116
+ it "should be marked as a proxy class" do
117
+ expect(env.net_http_class(proxied_host)).to be_proxy_class
118
+ end
119
+
120
+ it "should have the expected proxy attributes" do
121
+ http = env.net_http_class(proxied_host).new("www.kernel.org")
122
+ expected_attributes = {
123
+ "host" => env.http_proxy_uri.host,
124
+ "port" => env.http_proxy_uri.port,
125
+ "user" => env.http_proxy_uri.user,
126
+ "pass" => env.http_proxy_uri.password
127
+ }
128
+ actual_attributes = {
129
+ "host" => http.proxy_address,
130
+ "port" => http.proxy_port,
131
+ "user" => http.proxy_user,
132
+ "pass" => http.proxy_pass,
133
+ }
134
+
135
+ expect(actual_attributes).to eq expected_attributes
136
+ end
137
+
138
+ end
139
+
140
+ context "with an excluded host" do
141
+ with_env "http_proxy" => "admin:secret@example.com",
142
+ "no_proxy" => "no.proxy.com, noproxy.com"
143
+
144
+ context "with an exact match" do
145
+ let(:proxied_host) { "noproxy.com" }
146
+
147
+ it "should have the normal class" do
148
+ expect(env.net_http_class(proxied_host)).to be Net::HTTP
149
+ end
150
+
151
+ it "should not be marked as a proxy class" do
152
+ expect(env.net_http_class(proxied_host)).to_not be_proxy_class
153
+ end
154
+ end
155
+
156
+ context "with a subdomain match" do
157
+ let(:proxied_host) { "www.noproxy.com" }
158
+
159
+ it "should have the normal class" do
160
+ expect(env.net_http_class(proxied_host)).to be Net::HTTP
161
+ end
162
+
163
+ it "should not be marked as a proxy class" do
164
+ expect(env.net_http_class(proxied_host)).to_not be_proxy_class
165
+ end
166
+ end
167
+
168
+ context "with localhost" do
169
+ let(:proxied_host) { "localhost" }
170
+
171
+ it "should have the normal class" do
172
+ expect(env.net_http_class(proxied_host)).to be Net::HTTP
173
+ end
174
+
175
+ it "should not be marked as a proxy class" do
176
+ expect(env.net_http_class(proxied_host)).to_not be_proxy_class
177
+ end
178
+ end
179
+
180
+ context "with 127.0.0.1" do
181
+ let(:proxied_host) { "127.0.0.1" }
182
+
183
+ it "should have the normal class" do
184
+ expect(env.net_http_class(proxied_host)).to be Net::HTTP
185
+ end
186
+
187
+ it "should not be marked as a proxy class" do
188
+ expect(env.net_http_class(proxied_host)).to_not be_proxy_class
189
+ end
190
+ end
191
+
192
+ context "with a mismatch" do
193
+ let(:proxied_host) { "www.example.com" }
194
+
195
+ it "should have a subclass the normal class" do
196
+ expect(env.net_http_class(proxied_host)).to be < Net::HTTP
197
+ end
198
+
199
+ it "should be marked as a proxy class" do
200
+ expect(env.net_http_class(proxied_host)).to be_proxy_class
201
+ end
202
+ end
203
+
204
+ end
205
+
206
+ end
207
+
208
+ end
209
+ end
@@ -0,0 +1,162 @@
1
+ require "librarian/helpers"
2
+ require "librarian/lockfile/parser"
3
+ require "librarian/mock"
4
+
5
+ module Librarian
6
+ describe Lockfile::Parser do
7
+
8
+ let(:env) { Mock::Environment.new }
9
+ let(:parser) { described_class.new(env) }
10
+ let(:resolution) { parser.parse(lockfile) }
11
+
12
+ context "a mock lockfile with one source and no dependencies" do
13
+ let(:lockfile) do
14
+ Helpers.strip_heredoc <<-LOCKFILE
15
+ MOCK
16
+ remote: source-a
17
+ specs:
18
+
19
+ DEPENDENCIES
20
+
21
+ LOCKFILE
22
+ end
23
+
24
+ it "should give an empty list of dependencies" do
25
+ expect(resolution.dependencies).to be_empty
26
+ end
27
+
28
+ it "should give an empty list of manifests" do
29
+ expect(resolution.manifests).to be_empty
30
+ end
31
+ end
32
+
33
+ context "a mock lockfile with one source and one dependency" do
34
+ let(:lockfile) do
35
+ Helpers.strip_heredoc <<-LOCKFILE
36
+ MOCK
37
+ remote: source-a
38
+ specs:
39
+ jelly (1.3.5)
40
+
41
+ DEPENDENCIES
42
+ jelly (!= 1.2.6, ~> 1.1)
43
+
44
+ LOCKFILE
45
+ end
46
+
47
+ it "should give a list of one dependency" do
48
+ expect(resolution).to have(1).dependencies
49
+ end
50
+
51
+ it "should give a dependency with the expected name" do
52
+ dependency = resolution.dependencies.first
53
+
54
+ expect(dependency.name).to eq "jelly"
55
+ end
56
+
57
+ it "should give a dependency with the expected requirement" do
58
+ dependency = resolution.dependencies.first
59
+
60
+ # Note: it must be this order because this order is lexicographically sorted.
61
+ expect(dependency.requirement.to_s).to eq "!= 1.2.6, ~> 1.1"
62
+ end
63
+
64
+ it "should give a dependency wth the expected source" do
65
+ dependency = resolution.dependencies.first
66
+ source = dependency.source
67
+
68
+ expect(source.name).to eq "source-a"
69
+ end
70
+
71
+ it "should give a list of one manifest" do
72
+ expect(resolution).to have(1).manifests
73
+ end
74
+
75
+ it "should give a manifest with the expected name" do
76
+ manifest = resolution.manifests.first
77
+
78
+ expect(manifest.name).to eq "jelly"
79
+ end
80
+
81
+ it "should give a manifest with the expected version" do
82
+ manifest = resolution.manifests.first
83
+
84
+ expect(manifest.version.to_s).to eq "1.3.5"
85
+ end
86
+
87
+ it "should give a manifest with no dependencies" do
88
+ manifest = resolution.manifests.first
89
+
90
+ expect(manifest.dependencies).to be_empty
91
+ end
92
+
93
+ it "should give a manifest with the expected source" do
94
+ manifest = resolution.manifests.first
95
+ source = manifest.source
96
+
97
+ expect(source.name).to eq "source-a"
98
+ end
99
+
100
+ it "should give the dependency and the manifest the same source instance" do
101
+ dependency = resolution.dependencies.first
102
+ manifest = resolution.manifests.first
103
+
104
+ dependency_source = dependency.source
105
+ manifest_source = manifest.source
106
+
107
+ expect(manifest_source).to be dependency_source
108
+ end
109
+ end
110
+
111
+ context "a mock lockfile with one source and a complex dependency" do
112
+ let(:lockfile) do
113
+ Helpers.strip_heredoc <<-LOCKFILE
114
+ MOCK
115
+ remote: source-a
116
+ specs:
117
+ butter (2.5.3)
118
+ jelly (1.3.5)
119
+ butter (< 3, >= 1.1)
120
+
121
+ DEPENDENCIES
122
+ jelly (!= 1.2.6, ~> 1.1)
123
+
124
+ LOCKFILE
125
+ end
126
+
127
+ it "should give a list of one dependency" do
128
+ expect(resolution).to have(1).dependencies
129
+ end
130
+
131
+ it "should have the expected dependency" do
132
+ dependency = resolution.dependencies.first
133
+
134
+ expect(dependency.name).to eq "jelly"
135
+ end
136
+
137
+ it "should give a list of all the manifests" do
138
+ expect(resolution).to have(2).manifests
139
+ end
140
+
141
+ it "should include all the expected manifests" do
142
+ manifests = ManifestSet.new(resolution.manifests)
143
+
144
+ expect(manifests.to_hash.keys).to match_array( %w(butter jelly) )
145
+ end
146
+
147
+ it "should have an internally consistent set of manifests" do
148
+ manifests = ManifestSet.new(resolution.manifests)
149
+
150
+ expect(manifests).to be_consistent
151
+ end
152
+
153
+ it "should have an externally consistent set of manifests" do
154
+ dependencies = resolution.dependencies
155
+ manifests = ManifestSet.new(resolution.manifests)
156
+
157
+ expect(manifests).to be_in_compliance_with dependencies
158
+ end
159
+ end
160
+
161
+ end
162
+ end
@@ -0,0 +1,65 @@
1
+ require 'librarian'
2
+ require 'librarian/mock'
3
+
4
+ module Librarian
5
+ describe Lockfile do
6
+
7
+ let(:env) { Mock::Environment.new }
8
+
9
+ before do
10
+ env.registry :clear => true do
11
+ source 'source-1' do
12
+ spec 'alpha', '1.1'
13
+ end
14
+ end
15
+ end
16
+
17
+ let(:spec) do
18
+ env.dsl do
19
+ src 'source-1'
20
+ dep 'alpha', '1.1'
21
+ end
22
+ end
23
+
24
+ let(:resolver) { env.resolver }
25
+ let(:resolution) { resolver.resolve(spec) }
26
+
27
+ context "sanity" do
28
+ context "the resolution" do
29
+ subject { resolution }
30
+
31
+ it { should be_correct }
32
+ it { should have(1).manifests }
33
+ end
34
+ end
35
+
36
+ describe "#save" do
37
+ let(:lockfile) { env.ephemeral_lockfile }
38
+ let(:lockfile_text) { lockfile.save(resolution) }
39
+
40
+ context "just saving" do
41
+ it "should return the lockfile text" do
42
+ expect(lockfile_text).to_not be_nil
43
+ end
44
+ end
45
+
46
+ context "saving and reloading" do
47
+ let(:reloaded_resolution) { lockfile.load(lockfile_text) }
48
+
49
+ it "should have the expected manifests" do
50
+ expect(reloaded_resolution.manifests.count).to eq resolution.manifests.count
51
+ end
52
+ end
53
+
54
+ context "bouncing" do
55
+ let(:bounced_resolution) { lockfile.load(lockfile_text) }
56
+ let(:bounced_lockfile_text) { lockfile.save(bounced_resolution) }
57
+
58
+ it "should return the same lockfile text after bouncing as before bouncing" do
59
+ expect(bounced_lockfile_text).to eq lockfile_text
60
+ end
61
+ end
62
+ end
63
+
64
+ end
65
+ end
@@ -0,0 +1,11 @@
1
+ require "librarian/manifest"
2
+
3
+ describe Librarian::Manifest::Version do
4
+
5
+ describe "#inspect" do
6
+ subject(:version) { described_class.new("3.2.1") }
7
+
8
+ specify { expect(version.inspect).to eq "#<Librarian::Manifest::Version 3.2.1>" }
9
+ end
10
+
11
+ end