librarian 0.0.1

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 (65) hide show
  1. data/.gitignore +5 -0
  2. data/.rspec +2 -0
  3. data/Gemfile +4 -0
  4. data/MIT-LICENSE +20 -0
  5. data/README.md +46 -0
  6. data/Rakefile +13 -0
  7. data/bin/librarian-chef +7 -0
  8. data/bin/librarian-mock +7 -0
  9. data/config/cucumber.yaml +1 -0
  10. data/features/chef/cli/install.feature +69 -0
  11. data/features/support/env.rb +5 -0
  12. data/lib/librarian.rb +191 -0
  13. data/lib/librarian/chef.rb +1 -0
  14. data/lib/librarian/chef/cli.rb +14 -0
  15. data/lib/librarian/chef/dsl.rb +14 -0
  16. data/lib/librarian/chef/extension.rb +24 -0
  17. data/lib/librarian/chef/manifest.rb +43 -0
  18. data/lib/librarian/chef/particularity.rb +9 -0
  19. data/lib/librarian/chef/source.rb +3 -0
  20. data/lib/librarian/chef/source/git.rb +14 -0
  21. data/lib/librarian/chef/source/local.rb +80 -0
  22. data/lib/librarian/chef/source/path.rb +14 -0
  23. data/lib/librarian/chef/source/site.rb +271 -0
  24. data/lib/librarian/cli.rb +76 -0
  25. data/lib/librarian/dependency.rb +44 -0
  26. data/lib/librarian/dsl.rb +76 -0
  27. data/lib/librarian/dsl/receiver.rb +46 -0
  28. data/lib/librarian/dsl/target.rb +164 -0
  29. data/lib/librarian/helpers.rb +13 -0
  30. data/lib/librarian/helpers/debug.rb +35 -0
  31. data/lib/librarian/lockfile.rb +31 -0
  32. data/lib/librarian/lockfile/compiler.rb +69 -0
  33. data/lib/librarian/lockfile/parser.rb +102 -0
  34. data/lib/librarian/manifest.rb +88 -0
  35. data/lib/librarian/manifest_set.rb +131 -0
  36. data/lib/librarian/mock.rb +1 -0
  37. data/lib/librarian/mock/cli.rb +14 -0
  38. data/lib/librarian/mock/dsl.rb +14 -0
  39. data/lib/librarian/mock/extension.rb +28 -0
  40. data/lib/librarian/mock/particularity.rb +7 -0
  41. data/lib/librarian/mock/source.rb +1 -0
  42. data/lib/librarian/mock/source/mock.rb +88 -0
  43. data/lib/librarian/mock/source/mock/registry.rb +79 -0
  44. data/lib/librarian/particularity.rb +7 -0
  45. data/lib/librarian/resolution.rb +36 -0
  46. data/lib/librarian/resolver.rb +139 -0
  47. data/lib/librarian/source.rb +2 -0
  48. data/lib/librarian/source/git.rb +91 -0
  49. data/lib/librarian/source/git/repository.rb +82 -0
  50. data/lib/librarian/source/local.rb +33 -0
  51. data/lib/librarian/source/path.rb +52 -0
  52. data/lib/librarian/spec.rb +11 -0
  53. data/lib/librarian/spec_change_set.rb +169 -0
  54. data/lib/librarian/specfile.rb +16 -0
  55. data/lib/librarian/support/abstract_method.rb +21 -0
  56. data/lib/librarian/ui.rb +64 -0
  57. data/lib/librarian/version.rb +3 -0
  58. data/librarian.gemspec +29 -0
  59. data/spec/chef/git_source_spec.rb +93 -0
  60. data/spec/dsl_spec.rb +167 -0
  61. data/spec/lockfile_spec.rb +44 -0
  62. data/spec/meta/requires_spec.rb +27 -0
  63. data/spec/resolver_spec.rb +172 -0
  64. data/spec/spec_change_set_spec.rb +165 -0
  65. metadata +172 -0
data/spec/dsl_spec.rb ADDED
@@ -0,0 +1,167 @@
1
+ require 'librarian'
2
+ require 'librarian/mock'
3
+
4
+ module Librarian
5
+ module Mock
6
+
7
+ describe Dsl do
8
+
9
+ context "a single dependency but no applicable source" do
10
+
11
+ it "should not run without any sources" do
12
+ expect do
13
+ Dsl.run do
14
+ dep 'dependency-1'
15
+ end
16
+ end.to raise_error(Dsl::Error)
17
+ end
18
+
19
+ it "should not run when a block source is defined but the dependency is outside the block" do
20
+ expect do
21
+ Dsl.run do
22
+ src 'source-1' do end
23
+ dep 'dependency-1'
24
+ end
25
+ end.to raise_error(Dsl::Error)
26
+ end
27
+
28
+ end
29
+
30
+ context "a simple specfile - a single source, a single dependency, no transitive dependencies" do
31
+
32
+ it "should run with a hash source" do
33
+ spec = Dsl.run do
34
+ dep 'dependency-1',
35
+ :src => 'source-1'
36
+ end
37
+ spec.dependencies.should_not be_empty
38
+ spec.dependencies.first.name.should == 'dependency-1'
39
+ spec.dependencies.first.source.name.should == 'source-1'
40
+ spec.source.should be_nil
41
+ end
42
+
43
+ it "should run with a shortcut source" do
44
+ spec = Dsl.run do
45
+ dep 'dependency-1',
46
+ :source => :a
47
+ end
48
+ spec.dependencies.should_not be_empty
49
+ spec.dependencies.first.name.should == 'dependency-1'
50
+ spec.dependencies.first.source.name.should == 'source-a'
51
+ spec.source.should be_nil
52
+ end
53
+
54
+ it "should run with a block hash source" do
55
+ spec = Dsl.run do
56
+ source :src => 'source-1' do
57
+ dep 'dependency-1'
58
+ end
59
+ end
60
+ spec.dependencies.should_not be_empty
61
+ spec.dependencies.first.name.should == 'dependency-1'
62
+ spec.dependencies.first.source.name.should == 'source-1'
63
+ spec.source.should be_nil
64
+ end
65
+
66
+ it "should run with a block named source" do
67
+ spec = Dsl.run do
68
+ src 'source-1' do
69
+ dep 'dependency-1'
70
+ end
71
+ end
72
+ spec.dependencies.should_not be_empty
73
+ spec.dependencies.first.name.should == 'dependency-1'
74
+ spec.dependencies.first.source.name.should == 'source-1'
75
+ spec.source.should be_nil
76
+ end
77
+
78
+ it "should run with a default hash source" do
79
+ spec = Dsl.run do
80
+ source :src => 'source-1'
81
+ dep 'dependency-1'
82
+ end
83
+ spec.dependencies.should_not be_empty
84
+ spec.dependencies.first.name.should == 'dependency-1'
85
+ spec.dependencies.first.source.name.should == 'source-1'
86
+ spec.source.should_not be_nil
87
+ spec.dependencies.first.source.should == spec.source
88
+ end
89
+
90
+ it "should run with a default named source" do
91
+ spec = Dsl.run do
92
+ src 'source-1'
93
+ dep 'dependency-1'
94
+ end
95
+ spec.dependencies.should_not be_empty
96
+ spec.dependencies.first.name.should == 'dependency-1'
97
+ spec.dependencies.first.source.name.should == 'source-1'
98
+ spec.source.should_not be_nil
99
+ spec.dependencies.first.source.should == spec.source
100
+ end
101
+
102
+ it "should run with a default shortcut source" do
103
+ spec = Dsl.run do
104
+ source :a
105
+ dep 'dependency-1'
106
+ end
107
+ spec.dependencies.should_not be_empty
108
+ spec.dependencies.first.name.should == 'dependency-1'
109
+ spec.dependencies.first.source.name.should == 'source-a'
110
+ spec.source.should_not be_nil
111
+ spec.dependencies.first.source.should == spec.source
112
+ end
113
+
114
+ it "should run with a shortcut source hash definition" do
115
+ spec = Dsl.run do
116
+ source :b, :src => 'source-b'
117
+ dep 'dependency-1', :source => :b
118
+ end
119
+ spec.dependencies.should_not be_empty
120
+ spec.dependencies.first.name.should == 'dependency-1'
121
+ spec.dependencies.first.source.name.should == 'source-b'
122
+ spec.source.should be_nil
123
+ end
124
+
125
+ it "should run with a shortcut source block definition" do
126
+ spec = Dsl.run do
127
+ source :b, proc { src 'source-b' }
128
+ dep 'dependency-1', :source => :b
129
+ end
130
+ spec.dependencies.should_not be_empty
131
+ spec.dependencies.first.name.should == 'dependency-1'
132
+ spec.dependencies.first.source.name.should == 'source-b'
133
+ spec.source.should be_nil
134
+ end
135
+
136
+ it "should run with a default shortcut source hash definition" do
137
+ spec = Dsl.run do
138
+ source :b, :src => 'source-b'
139
+ source :b
140
+ dep 'dependency-1'
141
+ end
142
+ spec.dependencies.should_not be_empty
143
+ spec.dependencies.first.name.should == 'dependency-1'
144
+ spec.dependencies.first.source.name.should == 'source-b'
145
+ spec.source.should_not be_nil
146
+ spec.source.name.should == 'source-b'
147
+ end
148
+
149
+ it "should run with a default shortcut source block definition" do
150
+ spec = Dsl.run do
151
+ source :b, proc { src 'source-b' }
152
+ source :b
153
+ dep 'dependency-1'
154
+ end
155
+ spec.dependencies.should_not be_empty
156
+ spec.dependencies.first.name.should == 'dependency-1'
157
+ spec.dependencies.first.source.name.should == 'source-b'
158
+ spec.source.should_not be_nil
159
+ spec.source.name.should == 'source-b'
160
+ end
161
+
162
+ end
163
+
164
+ end
165
+
166
+ end
167
+ end
@@ -0,0 +1,44 @@
1
+ require 'librarian'
2
+ require 'librarian/mock'
3
+
4
+ module Librarian
5
+ describe Lockfile do
6
+
7
+ it "should save" do
8
+ Mock.registry :clear => true do
9
+ source 'source-1' do
10
+ spec 'alpha', '1.1'
11
+ end
12
+ end
13
+ spec = Mock.dsl do
14
+ src 'source-1'
15
+ dep 'alpha', '1.1'
16
+ end
17
+ resolution = Mock.resolver.resolve(spec)
18
+ resolution.should be_correct
19
+ lockfile = Mock.ephemeral_lockfile
20
+ lockfile_text = lockfile.save(resolution)
21
+ lockfile_text.should_not be_nil
22
+ end
23
+
24
+ it "should bounce" do
25
+ Mock.registry :clear => true do
26
+ source 'source-1' do
27
+ spec 'alpha', '1.1'
28
+ end
29
+ end
30
+ spec = Mock.dsl do
31
+ src 'source-1'
32
+ dep 'alpha', '1.1'
33
+ end
34
+ resolution = Mock.resolver.resolve(spec)
35
+ resolution.should be_correct
36
+ lockfile = Mock.ephemeral_lockfile
37
+ lockfile_text = lockfile.save(resolution)
38
+ bounced_resolution = lockfile.load(lockfile_text)
39
+ bounced_lockfile_text = lockfile.save(bounced_resolution)
40
+ bounced_lockfile_text.should == lockfile_text
41
+ end
42
+
43
+ end
44
+ end
@@ -0,0 +1,27 @@
1
+ require 'pathname'
2
+ require 'open3'
3
+
4
+ describe 'Meta' do
5
+ describe 'Requires', :slow => true do
6
+
7
+ root_path = Pathname.new('../../..').expand_path(__FILE__)
8
+
9
+ Pathname.glob(root_path.join('lib/**/*.rb')).sort.each do |path|
10
+
11
+ it "require '#{path.relative_path_from(root_path.join('lib'))}'" do
12
+ script = <<-SCRIPT
13
+ lib = File.expand_path(%{lib}, %{#{root_path}})
14
+ $:.unshift(lib) unless $:.include?(lib)
15
+ require %{#{path}}
16
+ SCRIPT
17
+ cmd = <<-CMD
18
+ ruby -e '#{script}'
19
+ CMD
20
+ err = Open3.popen3(cmd) { |i, o, e, t| e.read }
21
+ raise Exception, err if err != ''
22
+ end
23
+
24
+ end
25
+
26
+ end
27
+ end
@@ -0,0 +1,172 @@
1
+ require 'librarian'
2
+ require 'librarian/mock'
3
+
4
+ module Librarian
5
+ describe Resolver do
6
+
7
+ context "a simple specfile" do
8
+
9
+ it "should work" do
10
+ Mock.registry :clear => true do
11
+ source 'source-1' do
12
+ spec 'butter', '1.1'
13
+ end
14
+ end
15
+ spec = Mock.dsl do
16
+ src 'source-1'
17
+ dep 'butter'
18
+ end
19
+ resolver = Mock.resolver
20
+ resolution = resolver.resolve(spec)
21
+ resolution.should be_correct
22
+ end
23
+
24
+ end
25
+
26
+ context "a specfile with a dep from one src depending on a dep from another src" do
27
+
28
+ it "should work" do
29
+ Mock.registry :clear => true do
30
+ source 'source-1' do
31
+ spec 'butter', '1.1'
32
+ end
33
+ source 'source-2' do
34
+ spec 'jam', '1.2' do
35
+ dependency 'butter', '>= 1.0'
36
+ end
37
+ end
38
+ end
39
+ spec = Mock.dsl do
40
+ src 'source-1'
41
+ src 'source-2' do
42
+ dep 'jam'
43
+ end
44
+ end
45
+ resolver = Mock.resolver
46
+ resolution = resolver.resolve(spec)
47
+ resolution.should be_correct
48
+ end
49
+
50
+ end
51
+
52
+ context "a specfile with a dep depending on a nonexistent dep" do
53
+
54
+ it "should not work" do
55
+ Mock.registry :clear => true do
56
+ source 'source-1' do
57
+ spec 'jam', '1.2' do
58
+ dependency 'butter', '>= 1.0'
59
+ end
60
+ end
61
+ end
62
+ spec = Mock.dsl do
63
+ src 'source-1'
64
+ dep 'jam'
65
+ end
66
+ resolver = Mock.resolver
67
+ resolution = resolver.resolve(spec)
68
+ resolution.should_not be_correct
69
+ end
70
+
71
+ end
72
+
73
+ context "a specfile with conflicting constraints" do
74
+
75
+ it "should not work" do
76
+ Mock.registry :clear => true do
77
+ source 'source-1' do
78
+ spec 'butter', '1.0'
79
+ spec 'butter', '1.1'
80
+ spec 'jam', '1.2' do
81
+ dependency 'butter', '1.1'
82
+ end
83
+ end
84
+ end
85
+ spec = Mock.dsl do
86
+ src 'source-1'
87
+ dep 'butter', '1.0'
88
+ dep 'jam'
89
+ end
90
+ resolver = Mock.resolver
91
+ resolution = resolver.resolve(spec)
92
+ resolution.should_not be_correct
93
+ end
94
+
95
+ end
96
+
97
+ context "updating" do
98
+
99
+ it "should not work" do
100
+ Mock.registry :clear => true do
101
+ source 'source-1' do
102
+ spec 'butter', '1.0'
103
+ spec 'butter', '1.1'
104
+ spec 'jam', '1.2' do
105
+ dependency 'butter'
106
+ end
107
+ end
108
+ end
109
+ first_spec = Mock.dsl do
110
+ src 'source-1'
111
+ dep 'butter', '1.1'
112
+ dep 'jam'
113
+ end
114
+ first_resolution = Mock.resolver.resolve(first_spec)
115
+ first_resolution.should be_correct
116
+ first_manifests = first_resolution.manifests
117
+ first_manifests_index = Hash[first_manifests.map{|m| [m.name, m]}]
118
+ first_manifests_index['butter'].version.to_s.should == '1.1'
119
+
120
+ second_spec = Mock.dsl do
121
+ src 'source-1'
122
+ dep 'butter', '1.0'
123
+ dep 'jam'
124
+ end
125
+ locked_manifests = ManifestSet.deep_strip(first_manifests, ['butter'])
126
+ second_resolution = Mock.resolver.resolve(second_spec, locked_manifests)
127
+ second_resolution.should be_correct
128
+ second_manifests = second_resolution.manifests
129
+ second_manifests_index = Hash[second_manifests.map{|m| [m.name, m]}]
130
+ second_manifests_index['butter'].version.to_s.should == '1.0'
131
+ end
132
+
133
+ end
134
+
135
+ context "a change to the spec" do
136
+
137
+ it "should work" do
138
+ Mock.registry :clear => true do
139
+ source 'source-1' do
140
+ spec 'butter', '1.0'
141
+ end
142
+ source 'source-2' do
143
+ spec 'butter', '1.0'
144
+ end
145
+ end
146
+ spec = Mock.dsl do
147
+ src 'source-1'
148
+ dep 'butter'
149
+ end
150
+ lock = Mock.resolver.resolve(spec)
151
+ lock.should be_correct
152
+
153
+ spec = Mock.dsl do
154
+ src 'source-1'
155
+ dep 'butter', :src => 'source-2'
156
+ end
157
+ changes = Mock.spec_change_set(spec, lock)
158
+ changes.should_not be_same
159
+ manifests = ManifestSet.new(changes.analyze).to_hash
160
+ manifests.should_not have_key('butter')
161
+ lock = Mock.resolver.resolve(spec, changes.analyze)
162
+ lock.should be_correct
163
+ lock.manifests.map{|m| m.name}.should include('butter')
164
+ manifest = lock.manifests.find{|m| m.name == 'butter'}
165
+ manifest.should_not be_nil
166
+ manifest.source.name.should == 'source-2'
167
+ end
168
+
169
+ end
170
+
171
+ end
172
+ end
@@ -0,0 +1,165 @@
1
+ require 'librarian'
2
+ require 'librarian/mock'
3
+
4
+ module Librarian
5
+ describe SpecChangeSet do
6
+
7
+ context "a simple root removal" do
8
+
9
+ it "should work" do
10
+ Mock.registry :clear => true do
11
+ source 'source-1' do
12
+ spec 'butter', '1.0'
13
+ spec 'jam', '1.0'
14
+ end
15
+ end
16
+ spec = Mock.dsl do
17
+ src 'source-1'
18
+ dep 'butter'
19
+ dep 'jam'
20
+ end
21
+ lock = Mock.resolver.resolve(spec)
22
+ lock.should be_correct
23
+
24
+ spec = Mock.dsl do
25
+ src 'source-1'
26
+ dep 'jam'
27
+ end
28
+ changes = Mock.spec_change_set(spec, lock)
29
+ changes.should_not be_same
30
+
31
+ manifests = ManifestSet.new(changes.analyze).to_hash
32
+ manifests.should have_key('jam')
33
+ manifests.should_not have_key('butter')
34
+ end
35
+
36
+ end
37
+
38
+ context "a simple root add" do
39
+
40
+ it "should work" do
41
+ Mock.registry :clear => true do
42
+ source 'source-1' do
43
+ spec 'butter', '1.0'
44
+ spec 'jam', '1.0'
45
+ end
46
+ end
47
+ spec = Mock.dsl do
48
+ src 'source-1'
49
+ dep 'jam'
50
+ end
51
+ lock = Mock.resolver.resolve(spec)
52
+ lock.should be_correct
53
+
54
+ spec = Mock.dsl do
55
+ src 'source-1'
56
+ dep 'butter'
57
+ dep 'jam'
58
+ end
59
+ changes = Mock.spec_change_set(spec, lock)
60
+ changes.should_not be_same
61
+ manifests = ManifestSet.new(changes.analyze).to_hash
62
+ manifests.should have_key('jam')
63
+ manifests.should_not have_key('butter')
64
+ end
65
+
66
+ end
67
+
68
+ context "a simple root change" do
69
+
70
+ context "when the change is consistent" do
71
+
72
+ it "should work" do
73
+ Mock.registry :clear => true do
74
+ source 'source-1' do
75
+ spec 'butter', '1.0'
76
+ spec 'jam', '1.0'
77
+ spec 'jam', '1.1'
78
+ end
79
+ end
80
+ spec = Mock.dsl do
81
+ src 'source-1'
82
+ dep 'butter'
83
+ dep 'jam', '= 1.1'
84
+ end
85
+ lock = Mock.resolver.resolve(spec)
86
+ lock.should be_correct
87
+
88
+ spec = Mock.dsl do
89
+ src 'source-1'
90
+ dep 'butter'
91
+ dep 'jam', '>= 1.0'
92
+ end
93
+ changes = Mock.spec_change_set(spec, lock)
94
+ changes.should_not be_same
95
+ manifests = ManifestSet.new(changes.analyze).to_hash
96
+ manifests.should have_key('butter')
97
+ manifests.should have_key('jam')
98
+ end
99
+
100
+ end
101
+
102
+ context "when the change is inconsistent" do
103
+
104
+ it "should work" do
105
+ Mock.registry :clear => true do
106
+ source 'source-1' do
107
+ spec 'butter', '1.0'
108
+ spec 'jam', '1.0'
109
+ spec 'jam', '1.1'
110
+ end
111
+ end
112
+ spec = Mock.dsl do
113
+ src 'source-1'
114
+ dep 'butter'
115
+ dep 'jam', '= 1.0'
116
+ end
117
+ lock = Mock.resolver.resolve(spec)
118
+ lock.should be_correct
119
+
120
+ spec = Mock.dsl do
121
+ src 'source-1'
122
+ dep 'butter'
123
+ dep 'jam', '>= 1.1'
124
+ end
125
+ changes = Mock.spec_change_set(spec, lock)
126
+ changes.should_not be_same
127
+ manifests = ManifestSet.new(changes.analyze).to_hash
128
+ manifests.should have_key('butter')
129
+ manifests.should_not have_key('jam')
130
+ end
131
+
132
+ end
133
+
134
+ end
135
+
136
+ context "a simple root source change" do
137
+ it "should work" do
138
+ Mock.registry :clear => true do
139
+ source 'source-1' do
140
+ spec 'butter', '1.0'
141
+ end
142
+ source 'source-2' do
143
+ spec 'butter', '1.0'
144
+ end
145
+ end
146
+ spec = Mock.dsl do
147
+ src 'source-1'
148
+ dep 'butter'
149
+ end
150
+ lock = Mock.resolver.resolve(spec)
151
+ lock.should be_correct
152
+
153
+ spec = Mock.dsl do
154
+ src 'source-1'
155
+ dep 'butter', :src => 'source-2'
156
+ end
157
+ changes = Mock.spec_change_set(spec, lock)
158
+ changes.should_not be_same
159
+ manifests = ManifestSet.new(changes.analyze).to_hash
160
+ manifests.should_not have_key('butter')
161
+ end
162
+ end
163
+
164
+ end
165
+ end