librarian 0.0.9 → 0.0.10

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 (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