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.
- data/CHANGELOG.md +4 -0
- data/lib/librarian.rb +5 -178
- data/lib/librarian/action.rb +5 -0
- data/lib/librarian/action/base.rb +22 -0
- data/lib/librarian/action/clean.rb +56 -0
- data/lib/librarian/action/ensure.rb +24 -0
- data/lib/librarian/action/install.rb +101 -0
- data/lib/librarian/action/resolve.rb +81 -0
- data/lib/librarian/action/update.rb +76 -0
- data/lib/librarian/chef/cli.rb +7 -2
- data/lib/librarian/chef/dsl.rb +0 -3
- data/lib/librarian/chef/environment.rb +19 -0
- data/lib/librarian/chef/extension.rb +1 -16
- data/lib/librarian/chef/integration/knife.rb +9 -16
- data/lib/librarian/chef/source/git.rb +0 -2
- data/lib/librarian/chef/source/local.rb +1 -74
- data/lib/librarian/chef/source/local/manifest.rb +82 -0
- data/lib/librarian/chef/source/path.rb +0 -2
- data/lib/librarian/chef/source/site.rb +9 -89
- data/lib/librarian/chef/source/site/manifest.rb +94 -0
- data/lib/librarian/cli.rb +56 -17
- data/lib/librarian/dependency.rb +2 -2
- data/lib/librarian/dsl.rb +15 -5
- data/lib/librarian/dsl/receiver.rb +2 -0
- data/lib/librarian/dsl/target.rb +13 -1
- data/lib/librarian/environment.rb +94 -0
- data/lib/librarian/error.rb +4 -0
- data/lib/librarian/helpers/debug.rb +6 -6
- data/lib/librarian/lockfile.rb +7 -5
- data/lib/librarian/lockfile/compiler.rb +5 -4
- data/lib/librarian/lockfile/parser.rb +6 -5
- data/lib/librarian/manifest.rb +2 -2
- data/lib/librarian/mock/cli.rb +6 -1
- data/lib/librarian/mock/dsl.rb +0 -3
- data/lib/librarian/mock/environment.rb +24 -0
- data/lib/librarian/mock/extension.rb +1 -20
- data/lib/librarian/mock/source/mock.rb +7 -7
- data/lib/librarian/mock/source/mock/registry.rb +16 -12
- data/lib/librarian/resolver.rb +5 -116
- data/lib/librarian/resolver/implementation.rb +117 -0
- data/lib/librarian/source/git.rb +8 -7
- data/lib/librarian/source/git/repository.rb +7 -5
- data/lib/librarian/source/local.rb +1 -1
- data/lib/librarian/source/path.rb +7 -6
- data/lib/librarian/spec_change_set.rb +6 -5
- data/lib/librarian/specfile.rb +10 -4
- data/lib/librarian/version.rb +1 -1
- data/librarian.gemspec +1 -0
- data/spec/functional/chef/source/git_spec.rb +177 -89
- data/spec/functional/chef/source/site_spec.rb +111 -52
- data/spec/unit/action/base_spec.rb +18 -0
- data/spec/unit/action/clean_spec.rb +133 -0
- data/spec/unit/action/ensure_spec.rb +37 -0
- data/spec/unit/action/install_spec.rb +113 -0
- data/spec/unit/dsl_spec.rb +15 -13
- data/spec/unit/environment_spec.rb +9 -0
- data/spec/unit/lockfile_spec.rb +15 -4
- data/spec/unit/mock/source/mock.rb +22 -0
- data/spec/unit/resolver_spec.rb +24 -24
- data/spec/unit/spec_change_set_spec.rb +29 -25
- metadata +47 -19
- data/lib/librarian/chef/particularity.rb +0 -9
- data/lib/librarian/mock/particularity.rb +0 -9
- data/lib/librarian/particularity.rb +0 -7
@@ -0,0 +1,76 @@
|
|
1
|
+
require "librarian/error"
|
2
|
+
require "librarian/manifest_set"
|
3
|
+
require "librarian/resolver"
|
4
|
+
require "librarian/spec_change_set"
|
5
|
+
require "librarian/action/base"
|
6
|
+
|
7
|
+
module Librarian
|
8
|
+
module Action
|
9
|
+
class Update < Base
|
10
|
+
|
11
|
+
def run
|
12
|
+
unless lockfile_path.exist?
|
13
|
+
raise Error, "Lockfile missing!"
|
14
|
+
end
|
15
|
+
previous_resolution = lockfile.load(lockfile_path.read)
|
16
|
+
partial_manifests = ManifestSet.deep_strip(previous_resolution.manifests, dependency_names)
|
17
|
+
spec = specfile.read(previous_resolution.sources)
|
18
|
+
spec_changes = spec_change_set(spec, previous_resolution)
|
19
|
+
raise Error, "Cannot update when the specfile has been changed." unless spec_changes.same?
|
20
|
+
resolution = resolver.resolve(spec, partial_manifests)
|
21
|
+
unless resolution.correct?
|
22
|
+
raise Error, "Could not resolve the dependencies."
|
23
|
+
else
|
24
|
+
lockfile_text = lockfile.save(resolution)
|
25
|
+
debug { "Bouncing #{lockfile_name}" }
|
26
|
+
bounced_lockfile_text = lockfile.save(lockfile.load(lockfile_text))
|
27
|
+
unless bounced_lockfile_text == lockfile_text
|
28
|
+
debug { "lockfile_text: \n#{lockfile_text}"}
|
29
|
+
debug { "bounced_lockfile_text: \n#{bounced_lockfile_text}"}
|
30
|
+
raise Error, "Cannot bounce #{lockfile_name}!"
|
31
|
+
end
|
32
|
+
lockfile_path.open('wb') { |f| f.write(lockfile_text) }
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
private
|
37
|
+
|
38
|
+
def dependency_names
|
39
|
+
options[:names]
|
40
|
+
end
|
41
|
+
|
42
|
+
def specfile_name
|
43
|
+
environment.specfile_name
|
44
|
+
end
|
45
|
+
|
46
|
+
def lockfile_name
|
47
|
+
environment.lockfile_name
|
48
|
+
end
|
49
|
+
|
50
|
+
def specfile_path
|
51
|
+
environment.specfile_path
|
52
|
+
end
|
53
|
+
|
54
|
+
def lockfile_path
|
55
|
+
environment.lockfile_path
|
56
|
+
end
|
57
|
+
|
58
|
+
def specfile
|
59
|
+
environment.specfile
|
60
|
+
end
|
61
|
+
|
62
|
+
def lockfile
|
63
|
+
environment.lockfile
|
64
|
+
end
|
65
|
+
|
66
|
+
def resolver
|
67
|
+
Resolver.new(environment)
|
68
|
+
end
|
69
|
+
|
70
|
+
def spec_change_set(spec, lock)
|
71
|
+
SpecChangeSet.new(environment, spec, lock)
|
72
|
+
end
|
73
|
+
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
data/lib/librarian/chef/cli.rb
CHANGED
@@ -2,19 +2,24 @@ require 'librarian/helpers'
|
|
2
2
|
|
3
3
|
require 'librarian/cli'
|
4
4
|
require 'librarian/chef'
|
5
|
-
require 'librarian/chef/particularity'
|
6
5
|
|
7
6
|
module Librarian
|
8
7
|
module Chef
|
9
8
|
class Cli < Librarian::Cli
|
10
9
|
|
10
|
+
module Particularity
|
11
|
+
def root_module
|
12
|
+
Chef
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
11
16
|
include Particularity
|
12
17
|
extend Particularity
|
13
18
|
|
14
19
|
source_root Pathname.new(__FILE__).dirname.join("templates")
|
15
20
|
|
16
21
|
def init
|
17
|
-
copy_file
|
22
|
+
copy_file environment.specfile_name
|
18
23
|
end
|
19
24
|
|
20
25
|
end
|
data/lib/librarian/chef/dsl.rb
CHANGED
@@ -0,0 +1,19 @@
|
|
1
|
+
require "librarian/environment"
|
2
|
+
require "librarian/chef/dsl"
|
3
|
+
require "librarian/chef/source"
|
4
|
+
|
5
|
+
module Librarian
|
6
|
+
module Chef
|
7
|
+
class Environment < Environment
|
8
|
+
|
9
|
+
def specfile_name
|
10
|
+
"Cheffile"
|
11
|
+
end
|
12
|
+
|
13
|
+
def install_path
|
14
|
+
project_path.join("cookbooks")
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -1,24 +1,9 @@
|
|
1
|
-
require 'librarian/
|
2
|
-
require 'librarian/source'
|
3
|
-
require 'librarian/chef/dsl'
|
4
|
-
require 'librarian/chef/source'
|
1
|
+
require 'librarian/chef/environment'
|
5
2
|
|
6
3
|
module Librarian
|
7
4
|
module Chef
|
8
5
|
extend self
|
9
6
|
extend Librarian
|
10
7
|
|
11
|
-
module Overrides
|
12
|
-
def specfile_name
|
13
|
-
'Cheffile'
|
14
|
-
end
|
15
|
-
|
16
|
-
def install_path
|
17
|
-
project_path.join('cookbooks')
|
18
|
-
end
|
19
|
-
end
|
20
|
-
|
21
|
-
extend Overrides
|
22
|
-
|
23
8
|
end
|
24
9
|
end
|
@@ -1,13 +1,15 @@
|
|
1
|
+
require 'pathname'
|
1
2
|
require 'securerandom'
|
2
3
|
require 'highline'
|
3
4
|
|
4
5
|
require 'librarian'
|
6
|
+
require 'librarian/action/install'
|
5
7
|
require 'librarian/chef'
|
6
8
|
|
7
9
|
module Librarian
|
8
10
|
module Chef
|
9
11
|
|
10
|
-
|
12
|
+
class Environment
|
11
13
|
def install_path
|
12
14
|
@install_path ||= begin
|
13
15
|
has_home = ENV["HOME"] && File.directory?(ENV["HOME"])
|
@@ -22,28 +24,19 @@ module Librarian
|
|
22
24
|
end
|
23
25
|
end
|
24
26
|
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
raise Error, "#{specfile_name} missing!" unless specfile_path.exist?
|
29
|
-
raise Error, "#{lockfile_name} missing!" unless lockfile_path.exist?
|
27
|
+
def install_path
|
28
|
+
environment.install_path
|
29
|
+
end
|
30
30
|
|
31
|
-
|
32
|
-
spec = specfile.read(previous_resolution.sources)
|
33
|
-
spec_changes = spec_change_set(spec, previous_resolution)
|
34
|
-
raise Error, "#{specfile_name} and #{lockfile_name} are out of sync!" unless spec_changes.same?
|
31
|
+
hl = HighLine.new
|
35
32
|
|
36
|
-
|
37
|
-
|
38
|
-
end
|
33
|
+
begin
|
34
|
+
Action::Install.new(environment).run
|
39
35
|
rescue Error => e
|
40
|
-
hl = HighLine.new
|
41
36
|
message = hl.color(e.message, HighLine::RED)
|
42
37
|
hl.say(message)
|
43
38
|
Process.exit!(1)
|
44
39
|
end
|
45
40
|
|
46
|
-
install_consistent_resolution!
|
47
|
-
|
48
41
|
end
|
49
42
|
end
|
@@ -1,83 +1,10 @@
|
|
1
|
-
require '
|
2
|
-
require 'pathname'
|
3
|
-
|
4
|
-
require 'librarian/chef/manifest'
|
1
|
+
require 'librarian/chef/source/local/manifest'
|
5
2
|
|
6
3
|
module Librarian
|
7
4
|
module Chef
|
8
5
|
module Source
|
9
6
|
module Local
|
10
7
|
|
11
|
-
class Manifest < Manifest
|
12
|
-
|
13
|
-
class << self
|
14
|
-
|
15
|
-
def create(source, dependency, path)
|
16
|
-
new(source, dependency.name, path)
|
17
|
-
end
|
18
|
-
|
19
|
-
def manifest?(dependency, path)
|
20
|
-
path = Pathname.new(path)
|
21
|
-
!!manifest_path(path)
|
22
|
-
end
|
23
|
-
|
24
|
-
def check_manifest(dependency, manifest_path)
|
25
|
-
manifest = read_manifest(dependency.name, manifest_path)
|
26
|
-
manifest["name"] == dependency.name
|
27
|
-
end
|
28
|
-
|
29
|
-
end
|
30
|
-
|
31
|
-
attr_reader :path
|
32
|
-
|
33
|
-
def initialize(source, name, path)
|
34
|
-
super(source, name)
|
35
|
-
@path = Pathname.new(path)
|
36
|
-
@found_path = nil
|
37
|
-
end
|
38
|
-
|
39
|
-
def found_path
|
40
|
-
@found_path ||= source.manifest_search_paths(self).find{|p| self.class.manifest?(self, p)}
|
41
|
-
end
|
42
|
-
|
43
|
-
def manifest
|
44
|
-
@manifest ||= fetch_manifest!
|
45
|
-
end
|
46
|
-
|
47
|
-
def fetch_manifest!
|
48
|
-
expect_manifest
|
49
|
-
|
50
|
-
read_manifest(name, manifest_path(found_path))
|
51
|
-
end
|
52
|
-
|
53
|
-
def fetch_version!
|
54
|
-
manifest['version']
|
55
|
-
end
|
56
|
-
|
57
|
-
def fetch_dependencies!
|
58
|
-
manifest['dependencies']
|
59
|
-
end
|
60
|
-
|
61
|
-
def install!
|
62
|
-
debug { "Installing #{name}-#{version}" }
|
63
|
-
install_path = root_module.install_path.join(name)
|
64
|
-
if install_path.exist?
|
65
|
-
debug { "Deleting #{relative_path_to(install_path)}" }
|
66
|
-
install_path.rmtree
|
67
|
-
end
|
68
|
-
debug { "Copying #{relative_path_to(found_path)} to #{relative_path_to(install_path)}" }
|
69
|
-
FileUtils.cp_r(found_path, install_path)
|
70
|
-
end
|
71
|
-
|
72
|
-
private
|
73
|
-
|
74
|
-
def expect_manifest
|
75
|
-
return if found_path && manifest_path(found_path)
|
76
|
-
raise Error, "No metadata file found for #{name} from #{source}! If this should be a cookbook, you might consider contributing a metadata file upstream or forking the cookbook to add your own metadata file."
|
77
|
-
end
|
78
|
-
|
79
|
-
end
|
80
|
-
|
81
8
|
def manifest_class
|
82
9
|
Manifest
|
83
10
|
end
|
@@ -0,0 +1,82 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
require 'pathname'
|
3
|
+
|
4
|
+
require 'librarian/chef/manifest'
|
5
|
+
|
6
|
+
module Librarian
|
7
|
+
module Chef
|
8
|
+
module Source
|
9
|
+
module Local
|
10
|
+
class Manifest < Manifest
|
11
|
+
|
12
|
+
class << self
|
13
|
+
|
14
|
+
def create(source, dependency, path)
|
15
|
+
new(source, dependency.name, path)
|
16
|
+
end
|
17
|
+
|
18
|
+
def manifest?(dependency, path)
|
19
|
+
path = Pathname.new(path)
|
20
|
+
!!manifest_path(path)
|
21
|
+
end
|
22
|
+
|
23
|
+
def check_manifest(dependency, manifest_path)
|
24
|
+
manifest = read_manifest(dependency.name, manifest_path)
|
25
|
+
manifest["name"] == dependency.name
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
|
30
|
+
attr_reader :path
|
31
|
+
|
32
|
+
def initialize(source, name, path)
|
33
|
+
super(source, name)
|
34
|
+
@path = Pathname.new(path)
|
35
|
+
@found_path = nil
|
36
|
+
end
|
37
|
+
|
38
|
+
def found_path
|
39
|
+
@found_path ||= source.manifest_search_paths(self).find{|p| self.class.manifest?(self, p)}
|
40
|
+
end
|
41
|
+
|
42
|
+
def manifest
|
43
|
+
@manifest ||= fetch_manifest!
|
44
|
+
end
|
45
|
+
|
46
|
+
def fetch_manifest!
|
47
|
+
expect_manifest
|
48
|
+
|
49
|
+
read_manifest(name, manifest_path(found_path))
|
50
|
+
end
|
51
|
+
|
52
|
+
def fetch_version!
|
53
|
+
manifest['version']
|
54
|
+
end
|
55
|
+
|
56
|
+
def fetch_dependencies!
|
57
|
+
manifest['dependencies']
|
58
|
+
end
|
59
|
+
|
60
|
+
def install!
|
61
|
+
debug { "Installing #{name}-#{version}" }
|
62
|
+
install_path = environment.install_path.join(name)
|
63
|
+
if install_path.exist?
|
64
|
+
debug { "Deleting #{relative_path_to(install_path)}" }
|
65
|
+
install_path.rmtree
|
66
|
+
end
|
67
|
+
debug { "Copying #{relative_path_to(found_path)} to #{relative_path_to(install_path)}" }
|
68
|
+
FileUtils.cp_r(found_path, install_path)
|
69
|
+
end
|
70
|
+
|
71
|
+
private
|
72
|
+
|
73
|
+
def expect_manifest
|
74
|
+
return if found_path && manifest_path(found_path)
|
75
|
+
raise Error, "No metadata file found for #{name} from #{source}! If this should be a cookbook, you might consider contributing a metadata file upstream or forking the cookbook to add your own metadata file."
|
76
|
+
end
|
77
|
+
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
@@ -1,12 +1,10 @@
|
|
1
1
|
require 'librarian/source/path'
|
2
2
|
require 'librarian/chef/source/local'
|
3
|
-
require 'librarian/chef/particularity'
|
4
3
|
|
5
4
|
module Librarian
|
6
5
|
module Chef
|
7
6
|
module Source
|
8
7
|
class Path < Librarian::Source::Path
|
9
|
-
include Particularity
|
10
8
|
include Local
|
11
9
|
end
|
12
10
|
end
|
@@ -7,111 +7,31 @@ require 'digest'
|
|
7
7
|
|
8
8
|
require 'librarian/helpers/debug'
|
9
9
|
|
10
|
-
require 'librarian/manifest'
|
11
|
-
require 'librarian/chef/manifest'
|
12
|
-
require 'librarian/chef/particularity'
|
10
|
+
require 'librarian/chef/source/site/manifest'
|
13
11
|
|
14
12
|
module Librarian
|
15
13
|
module Chef
|
16
14
|
module Source
|
17
15
|
class Site
|
18
16
|
|
19
|
-
class Manifest < Manifest
|
20
|
-
|
21
|
-
attr_reader :version_uri
|
22
|
-
attr_reader :install_path
|
23
|
-
|
24
|
-
def initialize(source, name, version_uri = nil)
|
25
|
-
super(source, name)
|
26
|
-
@version_uri = version_uri
|
27
|
-
|
28
|
-
@cache_path = nil
|
29
|
-
@metadata_cache_path = nil
|
30
|
-
@package_cache_path = nil
|
31
|
-
@install_path = root_module.install_path.join(name)
|
32
|
-
|
33
|
-
@version_metadata = nil
|
34
|
-
@version_manifest = nil
|
35
|
-
end
|
36
|
-
|
37
|
-
def fetch_version!
|
38
|
-
version_metadata['version']
|
39
|
-
end
|
40
|
-
|
41
|
-
def fetch_dependencies!
|
42
|
-
version_manifest['dependencies'].map{|k, v| Dependency.new(k, v, nil)}
|
43
|
-
end
|
44
|
-
|
45
|
-
def version_uri
|
46
|
-
@version_uri ||= begin
|
47
|
-
source.cache!([self])
|
48
|
-
source.manifests(self).find{|m| m.version == version}.version_uri
|
49
|
-
end
|
50
|
-
end
|
51
|
-
|
52
|
-
def version_uri=(version_uri)
|
53
|
-
@version_uri = version_uri
|
54
|
-
end
|
55
|
-
|
56
|
-
def cache_path
|
57
|
-
@cache_path ||= source.version_cache_path(self, version_uri)
|
58
|
-
end
|
59
|
-
def metadata_cache_path
|
60
|
-
@metadata_cache_path ||= cache_path.join('version.json')
|
61
|
-
end
|
62
|
-
def package_cache_path
|
63
|
-
@package_cache_path ||= cache_path.join('package')
|
64
|
-
end
|
65
|
-
|
66
|
-
def version_metadata
|
67
|
-
@version_metadata ||= fetch_version_metadata!
|
68
|
-
end
|
69
|
-
|
70
|
-
def fetch_version_metadata!
|
71
|
-
source.cache_version_metadata!(self, version_uri)
|
72
|
-
JSON.parse(metadata_cache_path.read)
|
73
|
-
end
|
74
|
-
|
75
|
-
def version_manifest
|
76
|
-
@version_manifest ||= fetch_version_manifest!
|
77
|
-
end
|
78
|
-
|
79
|
-
def fetch_version_manifest!
|
80
|
-
source.cache_version_package!(self, version_uri, version_metadata['file'])
|
81
|
-
manifest_path = manifest_path(package_cache_path)
|
82
|
-
read_manifest(name, manifest_path)
|
83
|
-
end
|
84
|
-
|
85
|
-
def install!
|
86
|
-
debug { "Installing #{self}" }
|
87
|
-
version_manifest # make sure it's cached
|
88
|
-
if install_path.exist?
|
89
|
-
debug { "Deleting #{relative_path_to(install_path)}" }
|
90
|
-
install_path.rmtree
|
91
|
-
end
|
92
|
-
package_cache_path = source.version_package_cache_path(self, version_uri)
|
93
|
-
debug { "Copying #{relative_path_to(package_cache_path)} to #{relative_path_to(install_path)}" }
|
94
|
-
FileUtils.cp_r(package_cache_path, install_path)
|
95
|
-
end
|
96
|
-
|
97
|
-
end
|
98
|
-
|
99
17
|
include Helpers::Debug
|
100
|
-
include Particularity
|
101
18
|
|
102
19
|
class << self
|
103
20
|
LOCK_NAME = 'SITE'
|
104
21
|
def lock_name
|
105
22
|
LOCK_NAME
|
106
23
|
end
|
107
|
-
def from_lock_options(options)
|
108
|
-
new(options[:remote], options.reject{|k, v| k == :remote})
|
24
|
+
def from_lock_options(environment, options)
|
25
|
+
new(environment, options[:remote], options.reject{|k, v| k == :remote})
|
109
26
|
end
|
110
27
|
end
|
111
28
|
|
29
|
+
attr_accessor :environment
|
30
|
+
private :environment=
|
112
31
|
attr_reader :uri
|
113
32
|
|
114
|
-
def initialize(uri, options = {})
|
33
|
+
def initialize(environment, uri, options = {})
|
34
|
+
self.environment = environment
|
115
35
|
@uri = uri
|
116
36
|
@cache_path = nil
|
117
37
|
end
|
@@ -156,13 +76,13 @@ module Librarian
|
|
156
76
|
end
|
157
77
|
|
158
78
|
def install_path(dependency)
|
159
|
-
|
79
|
+
environment.install_path.join(dependency.name)
|
160
80
|
end
|
161
81
|
|
162
82
|
def cache_path
|
163
83
|
@cache_path ||= begin
|
164
84
|
dir = Digest::MD5.hexdigest(uri)
|
165
|
-
|
85
|
+
environment.cache_path.join("source/chef/site/#{dir}")
|
166
86
|
end
|
167
87
|
end
|
168
88
|
|