librarian 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
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