librarian 0.0.9 → 0.0.10

Sign up to get free protection for your applications and to get access to all the features.
Files changed (64) hide show
  1. data/CHANGELOG.md +4 -0
  2. data/lib/librarian.rb +5 -178
  3. data/lib/librarian/action.rb +5 -0
  4. data/lib/librarian/action/base.rb +22 -0
  5. data/lib/librarian/action/clean.rb +56 -0
  6. data/lib/librarian/action/ensure.rb +24 -0
  7. data/lib/librarian/action/install.rb +101 -0
  8. data/lib/librarian/action/resolve.rb +81 -0
  9. data/lib/librarian/action/update.rb +76 -0
  10. data/lib/librarian/chef/cli.rb +7 -2
  11. data/lib/librarian/chef/dsl.rb +0 -3
  12. data/lib/librarian/chef/environment.rb +19 -0
  13. data/lib/librarian/chef/extension.rb +1 -16
  14. data/lib/librarian/chef/integration/knife.rb +9 -16
  15. data/lib/librarian/chef/source/git.rb +0 -2
  16. data/lib/librarian/chef/source/local.rb +1 -74
  17. data/lib/librarian/chef/source/local/manifest.rb +82 -0
  18. data/lib/librarian/chef/source/path.rb +0 -2
  19. data/lib/librarian/chef/source/site.rb +9 -89
  20. data/lib/librarian/chef/source/site/manifest.rb +94 -0
  21. data/lib/librarian/cli.rb +56 -17
  22. data/lib/librarian/dependency.rb +2 -2
  23. data/lib/librarian/dsl.rb +15 -5
  24. data/lib/librarian/dsl/receiver.rb +2 -0
  25. data/lib/librarian/dsl/target.rb +13 -1
  26. data/lib/librarian/environment.rb +94 -0
  27. data/lib/librarian/error.rb +4 -0
  28. data/lib/librarian/helpers/debug.rb +6 -6
  29. data/lib/librarian/lockfile.rb +7 -5
  30. data/lib/librarian/lockfile/compiler.rb +5 -4
  31. data/lib/librarian/lockfile/parser.rb +6 -5
  32. data/lib/librarian/manifest.rb +2 -2
  33. data/lib/librarian/mock/cli.rb +6 -1
  34. data/lib/librarian/mock/dsl.rb +0 -3
  35. data/lib/librarian/mock/environment.rb +24 -0
  36. data/lib/librarian/mock/extension.rb +1 -20
  37. data/lib/librarian/mock/source/mock.rb +7 -7
  38. data/lib/librarian/mock/source/mock/registry.rb +16 -12
  39. data/lib/librarian/resolver.rb +5 -116
  40. data/lib/librarian/resolver/implementation.rb +117 -0
  41. data/lib/librarian/source/git.rb +8 -7
  42. data/lib/librarian/source/git/repository.rb +7 -5
  43. data/lib/librarian/source/local.rb +1 -1
  44. data/lib/librarian/source/path.rb +7 -6
  45. data/lib/librarian/spec_change_set.rb +6 -5
  46. data/lib/librarian/specfile.rb +10 -4
  47. data/lib/librarian/version.rb +1 -1
  48. data/librarian.gemspec +1 -0
  49. data/spec/functional/chef/source/git_spec.rb +177 -89
  50. data/spec/functional/chef/source/site_spec.rb +111 -52
  51. data/spec/unit/action/base_spec.rb +18 -0
  52. data/spec/unit/action/clean_spec.rb +133 -0
  53. data/spec/unit/action/ensure_spec.rb +37 -0
  54. data/spec/unit/action/install_spec.rb +113 -0
  55. data/spec/unit/dsl_spec.rb +15 -13
  56. data/spec/unit/environment_spec.rb +9 -0
  57. data/spec/unit/lockfile_spec.rb +15 -4
  58. data/spec/unit/mock/source/mock.rb +22 -0
  59. data/spec/unit/resolver_spec.rb +24 -24
  60. data/spec/unit/spec_change_set_spec.rb +29 -25
  61. metadata +47 -19
  62. data/lib/librarian/chef/particularity.rb +0 -9
  63. data/lib/librarian/mock/particularity.rb +0 -9
  64. data/lib/librarian/particularity.rb +0 -7
data/CHANGELOG.md CHANGED
@@ -1,3 +1,7 @@
1
+ ## 0.0.10
2
+
3
+ This release focuses on refactoring some of the internals. There are no functional changes.
4
+
1
5
  ## 0.0.9
2
6
 
3
7
  * \#11 Fixes a problem where, if the repo is in a path where a component has a space, attempting to resolve a
data/lib/librarian.rb CHANGED
@@ -1,188 +1,15 @@
1
- require 'pathname'
2
-
3
- require 'librarian/helpers/debug'
4
- require 'librarian/support/abstract_method'
5
-
6
1
  require 'librarian/version'
7
- require 'librarian/dependency'
8
- require 'librarian/manifest_set'
9
- require 'librarian/particularity'
10
- require 'librarian/resolver'
11
- require 'librarian/source'
12
- require 'librarian/spec_change_set'
13
- require 'librarian/specfile'
14
- require 'librarian/lockfile'
15
- require 'librarian/ui'
2
+ require 'librarian/environment'
16
3
 
17
4
  module Librarian
18
5
  extend self
19
6
 
20
- include Support::AbstractMethod
21
- include Helpers::Debug
22
-
23
- class Error < StandardError
24
- end
25
-
26
- attr_accessor :ui
27
-
28
- abstract_method :specfile_name, :dsl_class, :install_path
29
-
30
- def project_path
31
- @project_path ||= begin
32
- root = Pathname.new(Dir.pwd)
33
- root = root.dirname until root.join(specfile_name).exist? || root.dirname == root
34
- path = root.join(specfile_name)
35
- path.exist? ? root : nil
36
- end
37
- end
38
-
39
- def specfile_path
40
- project_path.join(specfile_name)
41
- end
42
-
43
- def specfile
44
- Specfile.new(self, specfile_path)
45
- end
46
-
47
- def lockfile_name
48
- "#{specfile_name}.lock"
49
- end
50
-
51
- def lockfile_path
52
- project_path.join(lockfile_name)
53
- end
54
-
55
- def lockfile
56
- Lockfile.new(self, lockfile_path)
57
- end
58
-
59
- def ephemeral_lockfile
60
- Lockfile.new(self, nil)
61
- end
62
-
63
- def resolver
64
- Resolver.new(self)
65
- end
66
-
67
- def cache_path
68
- project_path.join('tmp/librarian/cache')
7
+ def environment_class
8
+ self::Environment
69
9
  end
70
10
 
71
- def project_relative_path_to(path)
72
- Pathname.new(path).relative_path_from(project_path)
73
- end
74
-
75
- def spec_change_set(spec, lock)
76
- SpecChangeSet.new(self, spec, lock)
77
- end
78
-
79
- def version
80
- VERSION
81
- end
82
-
83
- def ensure!
84
- unless project_path
85
- raise Error, "Cannot find #{specfile_name}!"
86
- end
87
- end
88
-
89
- def clean!
90
- if cache_path.exist?
91
- debug { "Deleting #{project_relative_path_to(cache_path)}" }
92
- cache_path.rmtree
93
- end
94
- if install_path.exist?
95
- install_path.children.each do |c|
96
- debug { "Deleting #{project_relative_path_to(c)}" }
97
- c.rmtree unless c.file?
98
- end
99
- end
100
- if lockfile_path.exist?
101
- debug { "Deleting #{project_relative_path_to(lockfile_path)}" }
102
- lockfile_path.rmtree
103
- end
104
- end
105
-
106
- def install!
107
- resolve!
108
- manifests = ManifestSet.sort(lockfile.load(lockfile_path.read).manifests)
109
- manifests.each do |manifest|
110
- manifest.source.cache!([manifest])
111
- end
112
- install_path.mkpath unless install_path.exist?
113
- manifests.each do |manifest|
114
- manifest.install!
115
- end
116
- end
117
-
118
- def update!(dependency_names)
119
- unless lockfile_path.exist?
120
- raise Error, "Lockfile missing!"
121
- end
122
- previous_resolution = lockfile.load(lockfile_path.read)
123
- partial_manifests = ManifestSet.deep_strip(previous_resolution.manifests, dependency_names)
124
- spec = specfile.read(previous_resolution.sources)
125
- spec_changes = spec_change_set(spec, previous_resolution)
126
- raise Error, "Cannot update when the specfile has been changed." unless spec_changes.same?
127
- resolution = resolver.resolve(spec, partial_manifests)
128
- unless resolution.correct?
129
- ui.info { "Could not resolve the dependencies." }
130
- else
131
- lockfile_text = lockfile.save(resolution)
132
- debug { "Bouncing #{lockfile_name}" }
133
- bounced_lockfile_text = lockfile.save(lockfile.load(lockfile_text))
134
- unless bounced_lockfile_text == lockfile_text
135
- debug { "lockfile_text: \n#{lockfile_text}"}
136
- debug { "bounced_lockfile_text: \n#{bounced_lockfile_text}"}
137
- raise Error, "Cannot bounce #{lockfile_name}!"
138
- end
139
- lockfile_path.open('wb') { |f| f.write(lockfile_text) }
140
- end
141
- end
142
-
143
- def resolve!(options = {})
144
- if options[:force] || !lockfile_path.exist?
145
- spec = specfile.read
146
- manifests = []
147
- else
148
- lock = lockfile.read
149
- spec = specfile.read(lock.sources)
150
- changes = spec_change_set(spec, lock)
151
- if changes.same?
152
- debug { "The specfile is unchanged: nothing to do." }
153
- return
154
- end
155
- manifests = changes.analyze
156
- end
157
-
158
- resolution = resolver.resolve(spec, manifests)
159
- unless resolution.correct?
160
- raise Error, "Could not resolve the dependencies."
161
- else
162
- lockfile_text = lockfile.save(resolution)
163
- debug { "Bouncing #{lockfile_name}" }
164
- bounced_lockfile_text = lockfile.save(lockfile.load(lockfile_text))
165
- unless bounced_lockfile_text == lockfile_text
166
- debug { "lockfile_text: \n#{lockfile_text}"}
167
- debug { "bounced_lockfile_text: \n#{bounced_lockfile_text}"}
168
- raise Error, "Cannot bounce #{lockfile_name}!"
169
- end
170
- lockfile_path.open('wb') { |f| f.write(lockfile_text) }
171
- end
172
- end
173
-
174
- def dsl(&block)
175
- dsl_class.run(&block)
176
- end
177
-
178
- def dsl_class
179
- self::Dsl
180
- end
181
-
182
- private
183
-
184
- def root_module
185
- self
11
+ def environment
12
+ @environment ||= environment_class.new
186
13
  end
187
14
 
188
15
  end
@@ -0,0 +1,5 @@
1
+ require "librarian/action/clean"
2
+ require "librarian/action/ensure"
3
+ require "librarian/action/install"
4
+ require "librarian/action/resolve"
5
+ require "librarian/action/update"
@@ -0,0 +1,22 @@
1
+ require "librarian/helpers/debug"
2
+
3
+ module Librarian
4
+ module Action
5
+ class Base
6
+
7
+ include Helpers::Debug
8
+
9
+ attr_accessor :environment
10
+ private :environment=
11
+
12
+ attr_accessor :options
13
+ private :options=
14
+
15
+ def initialize(environment, options = { })
16
+ self.environment = environment
17
+ self.options = options
18
+ end
19
+
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,56 @@
1
+ require "librarian/action/base"
2
+
3
+ module Librarian
4
+ module Action
5
+ class Clean < Base
6
+
7
+ def run
8
+ clean_cache_path
9
+ clean_install_path
10
+ clean_lockfile_path
11
+ end
12
+
13
+ private
14
+
15
+ def clean_cache_path
16
+ if cache_path.exist?
17
+ debug { "Deleting #{project_relative_path_to(cache_path)}" }
18
+ cache_path.rmtree
19
+ end
20
+ end
21
+
22
+ def clean_install_path
23
+ if install_path.exist?
24
+ install_path.children.each do |c|
25
+ debug { "Deleting #{project_relative_path_to(c)}" }
26
+ c.rmtree unless c.file?
27
+ end
28
+ end
29
+ end
30
+
31
+ def clean_lockfile_path
32
+ if lockfile_path.exist?
33
+ debug { "Deleting #{project_relative_path_to(lockfile_path)}" }
34
+ lockfile_path.rmtree
35
+ end
36
+ end
37
+
38
+ def cache_path
39
+ environment.cache_path
40
+ end
41
+
42
+ def install_path
43
+ environment.install_path
44
+ end
45
+
46
+ def lockfile_path
47
+ environment.lockfile_path
48
+ end
49
+
50
+ def project_relative_path_to(path)
51
+ environment.project_relative_path_to(path)
52
+ end
53
+
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,24 @@
1
+ require "librarian/error"
2
+ require "librarian/action/base"
3
+
4
+ module Librarian
5
+ module Action
6
+ class Ensure < Base
7
+
8
+ def run
9
+ raise Error, "Cannot find #{specfile_name}!" unless project_path
10
+ end
11
+
12
+ private
13
+
14
+ def specfile_name
15
+ environment.specfile_name
16
+ end
17
+
18
+ def project_path
19
+ environment.project_path
20
+ end
21
+
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,101 @@
1
+ require "librarian/manifest_set"
2
+ require "librarian/spec_change_set"
3
+ require "librarian/action/base"
4
+
5
+ module Librarian
6
+ module Action
7
+ class Install < Base
8
+
9
+ def run
10
+ check_preconditions
11
+
12
+ perform_installation
13
+ end
14
+
15
+ private
16
+
17
+ def check_preconditions
18
+ check_specfile
19
+ check_lockfile
20
+ check_consistent
21
+ end
22
+
23
+ def check_specfile
24
+ raise Error, "#{specfile_name} missing!" unless specfile_path.exist?
25
+ end
26
+
27
+ def check_lockfile
28
+ raise Error, "#{lockfile_name} missing!" unless lockfile_path.exist?
29
+ end
30
+
31
+ def check_consistent
32
+ raise Error, "#{specfile_name} and #{lockfile_name} are out of sync!" unless spec_consistent_with_lock?
33
+ end
34
+
35
+ def perform_installation
36
+ manifests = sorted_manifests
37
+
38
+ cache_manifests(manifests)
39
+ create_install_path
40
+ install_manifests(manifests)
41
+ end
42
+
43
+ def cache_manifests(manifests)
44
+ manifests.each do |manifest|
45
+ manifest.source.cache!([manifest])
46
+ end
47
+ end
48
+
49
+ def create_install_path
50
+ install_path.mkpath unless install_path.exist?
51
+ end
52
+
53
+ def install_manifests(manifests)
54
+ manifests.each do |manifest|
55
+ manifest.install!
56
+ end
57
+ end
58
+
59
+ def sorted_manifests
60
+ ManifestSet.sort(lock.manifests)
61
+ end
62
+
63
+ def specfile_name
64
+ environment.specfile_name
65
+ end
66
+
67
+ def specfile_path
68
+ environment.specfile_path
69
+ end
70
+
71
+ def lockfile_name
72
+ environment.lockfile_name
73
+ end
74
+
75
+ def lockfile_path
76
+ environment.lockfile_path
77
+ end
78
+
79
+ def spec
80
+ environment.spec
81
+ end
82
+
83
+ def lock
84
+ environment.lock
85
+ end
86
+
87
+ def spec_change_set(spec, lock)
88
+ SpecChangeSet.new(environment, spec, lock)
89
+ end
90
+
91
+ def spec_consistent_with_lock?
92
+ spec_change_set(spec, lock).same?
93
+ end
94
+
95
+ def install_path
96
+ environment.install_path
97
+ end
98
+
99
+ end
100
+ end
101
+ end
@@ -0,0 +1,81 @@
1
+ require "librarian/error"
2
+ require "librarian/resolver"
3
+ require "librarian/spec_change_set"
4
+ require "librarian/action/base"
5
+
6
+ module Librarian
7
+ module Action
8
+ class Resolve < Base
9
+
10
+ def run
11
+ if force? || !lockfile_path.exist?
12
+ spec = specfile.read
13
+ manifests = []
14
+ else
15
+ lock = lockfile.read
16
+ spec = specfile.read(lock.sources)
17
+ changes = spec_change_set(spec, lock)
18
+ if changes.same?
19
+ debug { "The specfile is unchanged: nothing to do." }
20
+ return
21
+ end
22
+ manifests = changes.analyze
23
+ end
24
+
25
+ resolution = resolver.resolve(spec, manifests)
26
+ unless resolution.correct?
27
+ raise Error, "Could not resolve the dependencies."
28
+ else
29
+ lockfile_text = lockfile.save(resolution)
30
+ debug { "Bouncing #{lockfile_name}" }
31
+ bounced_lockfile_text = lockfile.save(lockfile.load(lockfile_text))
32
+ unless bounced_lockfile_text == lockfile_text
33
+ debug { "lockfile_text: \n#{lockfile_text}"}
34
+ debug { "bounced_lockfile_text: \n#{bounced_lockfile_text}"}
35
+ raise Error, "Cannot bounce #{lockfile_name}!"
36
+ end
37
+ lockfile_path.open('wb') { |f| f.write(lockfile_text) }
38
+ end
39
+ end
40
+
41
+ private
42
+
43
+ def force?
44
+ options[:force]
45
+ end
46
+
47
+ def specfile_name
48
+ environment.specfile_name
49
+ end
50
+
51
+ def lockfile_name
52
+ environment.lockfile_name
53
+ end
54
+
55
+ def specfile_path
56
+ environment.specfile_path
57
+ end
58
+
59
+ def lockfile_path
60
+ environment.lockfile_path
61
+ end
62
+
63
+ def specfile
64
+ environment.specfile
65
+ end
66
+
67
+ def lockfile
68
+ environment.lockfile
69
+ end
70
+
71
+ def resolver
72
+ Resolver.new(environment)
73
+ end
74
+
75
+ def spec_change_set(spec, lock)
76
+ SpecChangeSet.new(environment, spec, lock)
77
+ end
78
+
79
+ end
80
+ end
81
+ end